Advertisement
Guest User

Untitled

a guest
Mar 22nd, 2023
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.31 KB | None | 0 0
  1. import sys # We need sys so that we can pass argv to QApplication
  2. import asyncio
  3. from uio.utils import ctypes
  4. from uio.ti.icss import Icss
  5. from uio.ti.pwmss import Pwmss
  6. from ctypes import c_uint32 as uint32, c_uint8 as uint8, c_uint16 as uint16,c_int16 as int16, c_uint64 as uint64, c_char as char, c_int32 as int32, c_bool as boolean, Structure
  7. from ctypes import sizeof as c_sizeof
  8. from pathlib import Path
  9. from time import sleep
  10. import numpy as np
  11. import csv
  12.  
  13. pruss = Icss( "/dev/uio/pruss/module" )
  14. core_1 = pruss.core1
  15. frequency= 10000
  16. period = None
  17. divider = 1
  18. position = None
  19. weight = None
  20. pruvars = None
  21. top_motor_speed = period
  22. current_motor_speed = None
  23. maxloadposition = None
  24. minloadposition = None
  25. last_timestamp_cycles = 0
  26. stepper_step = None
  27. stepper_direction = None
  28. server1 = None
  29. server2 = None
  30. coro1 = None
  31. coro2 = None
  32. data_queue = None
  33. active_run = None
  34. shut_down = None
  35. NUM_MSGS = None
  36. ddr_layout = None
  37. shmem = None
  38. msgbuf = None
  39. ddr_widx = None
  40. ddr_layout = None
  41. rdix = 0
  42. wdix = 0
  43. lastid = 0
  44. timestamp_cycles = 0
  45. last_encoder_count = uint32(0)
  46. last_encoder_angle = 0
  47. encoder_count = uint32(0)
  48. encoder_angle = 0
  49. tare_coeff = None  
  50. emi_coeff = None
  51. val_stream = None
  52. line_count = 0
  53. pruss.initialize()
  54. period = round( 100e6 / divider / frequency )
  55. top_motor_speed = period
  56. pruss.uart.initialize(baudrate = 460800)
  57. magnet = Pwmss( "/dev/uio/pwmss1" ).pwm
  58. magnet.initialize(period,divider)
  59. current_magnet_speed = 0
  60.  
  61. # used to communicate ddr layout to C program
  62. class DDRLayout( Structure ):
  63.     _fields_ = [
  64.             ( 'msgbuf',      uint32 ),
  65.             ( 'num_msgs',    uint16 ),
  66.             ( 'msg_size',    uint16 ),
  67.         ]
  68.        
  69. # volatile variables in pruss shared memory
  70. class SharedVars( Structure ):
  71.     _fields_ = [
  72.         ( 'abort_file',    uint32),
  73.         ( 'abort_line',    uint32),
  74.         ( 'time',          uint32),
  75.                 ( 'ridx',          uint16),
  76.         ( 'cycle_limit',   uint16),
  77.         ( 'time_limit',    uint16),
  78.         ( 'signal_length', uint16),
  79.         ( 'signal', uint16*2000)
  80.     ]
  81.  
  82. class Message( ctypes.Structure ):
  83.     _fields_ = [
  84.         ( 'id', uint32 ),
  85.         ('timestamp', uint32),
  86.         ('control_signal', int32),
  87.         ('voltage', int32),
  88.         ('force', int16),
  89.                 ('cycle_count', uint16),
  90.         ('counter', uint16),
  91.                 ('signal_length', uint16)
  92.     ]
  93.  
  94. class Gpio:
  95.     def __init__( self, name ):
  96.         self.name = name
  97.         self._value_path = Path( '/dev/gpio', name, 'value' )
  98.  
  99.     def get_value( self ):
  100.         return int( self._value_path.read_text() )
  101.  
  102.     def set_value( self, value ):
  103.         self._value_path.write_text( str( value ) )
  104.  
  105.  
  106. def StopEM100():
  107.     pruss.uart.io.write( b'FFV\r', discard=True, flush=True )  # interrupt continuous transmission
  108.     sleep( 0.1 )  # make sure that response has been received
  109.     pruss.uart.io.discard()  # discard response
  110.  
  111.  
  112. def check_core():
  113.     if not core_1.halted:
  114.         return
  115.     if core_1.state.crashed:
  116.         msg = f'core crashed at pc={core_1.pc}'
  117.     elif shmem.abort_file == 0:
  118.         msg = f'core halted at pc={core_1.pc}'
  119.     else:
  120.         # FIXME figure out better way to read C-string from PRU memory
  121.         abort_file = core_1.read( char * 32, shmem.abort_file ).value
  122.         abort_file = abort_file.decode("ascii")
  123.         msg = f'core aborted at pc={core_1.pc} ({abort_file}:{shmem.abort_line})'
  124.     # dump some potentially interesting information:
  125.     msg += f'\n   ridx       = {ridx}'
  126.     msg += f'\n   shmem.ridx = {shmem.ridx}'
  127.     msg += f'\n   ddr_widx   = {ddr_widx.value}'
  128.     exit( msg )
  129.     astid = 0
  130.     print(f'placed signal limit value of {shmem.signal_length}')
  131. def recv_messages():   
  132.     # read updated write-pointer
  133.     global widx
  134.     global ridx
  135.     global lastid
  136.     global timestamp_cycles
  137.     widx = ddr_widx.value
  138.     assert widx < NUM_MSGS  # sanity-check
  139.  
  140.     if widx == ridx:
  141.         return  # nothing to do
  142.  
  143.     txdata = ''
  144.  
  145.     # process batch of messages
  146.  
  147.     # note: it may be faster to copy a batch of messages from shared memory
  148.     # instead of directly accessing individual messages and their fields.
  149.     while ridx != widx:
  150.         msg = msgbuf[ ridx ]
  151.  
  152.         # sanity-check that message id increments monotonically
  153.         # (i.e. no messages from pru got dropped)
  154.         dropped = ( msg.id - lastid - 1 ) & 0xffffffff
  155.         if dropped != 0:
  156.             raise RuntimeError( f'{dropped} messages dropped by PRU (0x{lastid:08x} -> 0x{msg.id:08x})' )
  157.         lastid = msg.id
  158.  
  159.         # get 32-bit timestamp (in cycles) from message and unwrap it:
  160.         timestamp_cycles += ( msg.timestamp - timestamp_cycles ) & 0xfffffff
  161.  
  162.         # convert to timestamp in seconds    
  163.            
  164.         force = int(msg.force )
  165.         voltage = int(msg.voltage)
  166.         signal = int(msg.control_signal)
  167.         counter = int(msg.counter)
  168.         cycle_count = int(msg.cycle_count)
  169.         signal_length = int(msg.signal_length)
  170.         timestamp_ms = timestamp_cycles // 200000
  171.         timestamp_s = ( timestamp_ms % 60000 ) / 1000
  172.         timestamp_m = timestamp_ms // 60000
  173.         timestamp_h = timestamp_m // 60
  174.         timestamp_m = timestamp_m % 60
  175.         timestamp_label = f'{timestamp_h:02d}:{timestamp_m:02d}:{timestamp_s:06.3f}'
  176.         time = timestamp_s + timestamp_m*60 + timestamp_h *360
  177.         txmsg = [time, timestamp_label,force,voltage,signal,cycle_count,counter,signal_length]
  178.         txdata += ','.join(map( str, txmsg )) + '\n'
  179.         # or just:  txdata += f'{self.timestamp_cycles},{force},{angle}\n'
  180.  
  181.         # consume message and update read pointer
  182.         ridx += 1
  183.         if (ridx == NUM_MSGS):
  184.             ridx = 0
  185.         del msg
  186.         shmem.ridx = ridx  # direct access to message forbidden beyond this point
  187.  
  188.         # send data to client
  189.         #writer.writerow( txdata.encode('ascii') )
  190.         writer.writerow( txmsg )
  191.  
  192.         # TODO maybe bail out with an error if too much data buffered in the writer?
  193.         # you can check with writer.get_write_buffer_size()
  194.  
  195.         print( f'\ridx=0x{ridx:04x} id=0x{lastid:08x} time={timestamp_label} force={force:08d} control signal={signal:08d} voltage={voltage:08d} counter={counter:08d}', end='', flush=True )
  196.  
  197. current_magnet_speed = 0
  198. magnet_direction = Gpio('magnet-dir')
  199. magnet_direction.set_value( 0 )
  200. data_queue = asyncio.Queue()
  201. stop_active_run = False
  202. shut_down = False
  203. ddr = pruss.ddr
  204.  
  205. core_1.load('direct_control.out')
  206. # if you don't want the ringbuffer at the start of the ddr region, specify offset here
  207. MSGBUF_OFFSET = 0
  208. # you can use a fixed ringbuffer size:
  209. #NUM_MSGS = 1024
  210. # or you can scale the ringbuffer to fit the size of the ddr region:
  211. NUM_MSGS = (ddr.size - MSGBUF_OFFSET - c_sizeof( uint16 ) ) // c_sizeof( Message )
  212. NUM_MSGS = min( NUM_MSGS, 65535 )  # make sure number of messages fits in u16
  213. # map shared memory variables
  214. ddr_layout = core_1.map( DDRLayout, 0x10000 )
  215. shmem = core_1.map( SharedVars, 0x10100 )
  216. msgbuf = ddr.map( Message * NUM_MSGS, MSGBUF_OFFSET )
  217. ddr_widx = ddr.map( uint16, MSGBUF_OFFSET + c_sizeof( msgbuf ) )
  218. # inform pru about layout of shared ddr memory region
  219. ddr_layout.msgbuf = ddr.address + MSGBUF_OFFSET
  220. ddr_layout.num_msgs = NUM_MSGS
  221. ddr_layout.msg_size = c_sizeof( Message )        
  222.                
  223. # local copies of read-pointer and write-pointer
  224. ridx = 0
  225. widx = 0
  226.  
  227. # initialize pointers in shared memory
  228. shmem.ridx = ridx
  229. ddr_widx.value = widx
  230.  
  231.  
  232. #loading wave profile
  233. with open('./steps_direct.csv','r') as f:
  234.     signal_reader = csv.reader(f)
  235.     for line in signal_reader:
  236.         shmem.signal[line_count] = int(line[0])
  237.         line_count += 1
  238. print(f' Loaded {line_count} lines in the file')
  239.  
  240. shmem.cycle_limit = 750
  241. shmem.signal_length = line_count
  242.  
  243. #open file for writing
  244. data_file = open('run_data.csv', 'w', newline='')
  245. writer = csv.writer(data_file)
  246. header = ['time','timestamp', 'force_g', 'voltage','signal','cycle_count','counter','signal_length']
  247. writer.writerow(header)
  248. # ready, set, go!
  249.  
  250. print('lauching core 1')
  251. pruss.ecap.pwm.initialize( 2**32 )
  252. core_1.run()
  253. sleep(.00001)
  254. try:
  255.     while (stop_active_run == False and shut_down == False):
  256.         recv_messages()
  257.         check_core()
  258.         sleep(0)
  259.  
  260. except KeyboardInterrupt:
  261.     pass
  262.  
  263. finally:
  264.    
  265.     print( '', flush=True )
  266.     StopEM100()
  267.     core_1.halt()
  268.  
  269.  
  270.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement