Advertisement
Guest User

Untitled

a guest
Mar 22nd, 2023
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.75 KB | None | 0 0
  1. #include <stdlib.h>
  2. #include <stdint.h>
  3. #include <stddef.h>
  4. #include "pru_uart.h"
  5. #include "pru_ecap.h"
  6. #include "sys_gpio.h"
  7.  
  8. // define PWM inputs for motor controll
  9. #define EPWM1A  ( *(uint16_t volatile *)0x48302212 )
  10. #define EPWM1B  ( *(uint16_t volatile *)0x48302214 )
  11.  
  12. // encoder position in other PRU core's memory
  13. #define position_var ((uint32_t const volatile *)0x00002000)
  14.  
  15. struct Message {
  16.     uint32_t id;
  17.     uint32_t timestamp;
  18.     int32_t control_signal;
  19.     int32_t magnet_voltage;
  20.     int16_t force;
  21.     int16_t cycle_count;
  22.     uint16_t counter;
  23.     uint16_t signal_length;
  24. };
  25.  
  26. // layout of shared ddr3 memory (filled in by loader)
  27. struct DDRLayout {
  28.     Message volatile *msgbuf;
  29.     uint16_t num_msgs;
  30.     uint16_t msg_size;
  31. };
  32.  
  33. struct SharedVars {
  34.     // set by pru before halting
  35.     char const *abort_file;
  36.     int abort_line;
  37.     uint32_t time;
  38.     // read-pointer updated by python
  39.     uint16_t ridx;
  40.     uint16_t cycle_limit;
  41.     uint16_t time_limit;
  42.     uint16_t signal_length;
  43.     uint16_t signal[2000];
  44. };
  45.  
  46. far struct DDRLayout ddr __attribute__((location(0x10000))) = {};
  47. far struct SharedVars volatile shmem __attribute__((location(0x10100))) = {};
  48.  
  49. static inline uint32_t timestamp_cycles()
  50. {
  51.     return CT_ECAP.TSCTR;
  52. }
  53.  
  54. // for easier debugging, record where in the source code we halted
  55. __attribute__((noreturn))
  56. void abort_at( char const *file, int line )
  57. {
  58.     shmem.abort_file = file;
  59.     shmem.abort_line = line;
  60.     for(;;) __halt();
  61. }
  62.  
  63. static inline void assert_at( bool cond, char const *file, int line )
  64. {
  65.     if( ! cond )
  66.         abort_at( file, line );
  67. }
  68.  
  69. #define abort() abort_at( __FILE__, __LINE__ )
  70. #define assert(cond) assert_at( (cond), __FILE__, __LINE__ )
  71.  
  72. // local copy of write-pointer
  73. static uint16_t widx = 0;
  74.  
  75. // global var for write-pointer is located right after message ringbuffer
  76. #define ddr_msgbuf_end  ( ddr.msgbuf + ddr.num_msgs )
  77. #define ddr_widx    ( *(uint16_t volatile *)ddr_msgbuf_end )
  78.  
  79. // receive byte from uart
  80. static inline char uart_recv_byte()
  81. {
  82.     for(;;) {
  83.         uint8_t lsr = CT_UART.LSR;
  84.         if( lsr & 0x1e )
  85.             abort();  // receive-error occurred
  86.         if( lsr & 0x01 )
  87.             return (char) CT_UART.RBR;
  88.     }
  89. }
  90.  
  91.  
  92. // receive CR-terminated line from uart
  93. static inline uint8_t uart_recv_line( char volatile msg[], uint8_t maxlen )
  94. {
  95.     uint8_t len = 0;
  96.  
  97.     for(;;) {
  98.         char c = uart_recv_byte();
  99.         if( c == '\r' )
  100.             break;  // found end of line
  101.         if( len == maxlen )
  102.             abort();  // line does not fit in buffer
  103.         msg[ len++ ] = c;
  104.     }
  105.  
  106.     return len;
  107. }
  108.  
  109.  
  110. int16_t receive_measurement()
  111. {
  112.     // allocate buffer at fixed address for debugging convenience
  113.     static char volatile msg[8] __attribute__((location(0x1f00)));
  114.  
  115.     // receive line from uart
  116.     uint8_t len = uart_recv_line( msg, sizeof msg );
  117.  
  118.     // verify length and prefix
  119.     if( len != 8 || msg[0] != 'N' || (msg[1] != '+' && msg[1] != '-'))
  120.         abort();
  121.  
  122.     // parse the remainder as integer
  123.     int16_t value = 0;
  124.     uint8_t i;
  125.     for( i = 2; i < len; i++ ) {
  126.         if( msg[i] < '0' || msg[i] > '9' )
  127.             abort();
  128.         value = value * 10 + ( msg[i] - '0' );
  129.     }
  130.     if (msg[1] == '-')
  131.             value *= -1;
  132.  
  133.     return value;
  134. }
  135.  
  136.  
  137. void initialize()
  138. {
  139.     // perform sanity-checking
  140.     assert( 0x80000000 <= (uint32_t)ddr.msgbuf );
  141.     assert( ddr.msgbuf < ddr_msgbuf_end );
  142.     assert( ddr.msg_size == sizeof(Message) );
  143.  
  144.     assert( ddr_widx == widx );
  145.     assert( shmem.ridx == widx );
  146. }
  147.  
  148.  
  149. static inline uint16_t next_idx( uint16_t idx )
  150. {
  151.     if( ++idx == ddr.num_msgs )
  152.         idx = 0;
  153.     return idx;
  154. }
  155.  
  156.  
  157. void send_message( uint32_t id, int16_t current_force,  int32_t input, int32_t output, uint16_t cycle,uint16_t counter, uint16_t signal_length)
  158. {
  159.     uint16_t next_widx = next_idx( widx );
  160.  
  161.     if( next_widx == shmem.ridx ) {
  162.         // can't send message, ringbuffer is full
  163.         abort();
  164.     }
  165.  
  166.     Message volatile *msg = &ddr.msgbuf[ widx ];
  167.  
  168.     // fill in contents of message
  169.     msg->id = id;
  170.     msg->force = current_force;
  171.     msg->timestamp = timestamp_cycles();
  172.     msg->control_signal = input;
  173.     msg->magnet_voltage = output;
  174.     msg->cycle_count = cycle;
  175.     msg->counter = counter;
  176.     msg->signal_length = signal_length;
  177.     // update write-pointer
  178.     ddr_widx = widx = next_widx;
  179. }
  180.  
  181. void main() {
  182.         int32_t control_signal = 0;
  183.     int32_t error[3];
  184.         CT_UART.THR = 'S';
  185.         CT_UART.THR = 'N';
  186.         CT_UART.THR = '\r';
  187.         initialize();
  188.    
  189.     uint32_t id =0;
  190.         int16_t reference_force = receive_measurement(); // initil reading from load cell      
  191.  
  192.     uint16_t counter = 0;
  193.         gpio_set_one_low(&GPIO0,31);
  194.  
  195.     // PID parameers
  196.     int32_t Kp = (int)(40 * (1 << 16)) ; // 20
  197.         int32_t Ki = (int)(0.005 * (1 << 16)) ; // 0.5
  198.         int32_t Kd = (int)(1 * (1 << 16)) ;// 0.4
  199.  
  200.         int32_t A[3] = {0};
  201.     A[0] = Kp + Ki + Kd;
  202.     A[1] = -Kp -2*Kd;
  203.     A[2] = Kd;
  204.    
  205.     uint16_t cycle_count = 0;
  206.     bool running = true;
  207.     uint16_t last_cycle = shmem.cycle_limit;
  208.     uint16_t time_limit = shmem.time_limit;
  209.     uint16_t signal_length = shmem.signal_length;
  210.     while (running) {
  211.         if (cycle_count <= last_cycle)
  212.         {
  213.        
  214.             int16_t force = receive_measurement();
  215.             int32_t input_signal = shmem.signal[counter];  
  216.        
  217.                 EPWM1A = abs(input_signal);
  218.             //report to python
  219.             send_message( ++id,force, input_signal,control_signal,cycle_count,counter,signal_length);
  220.             ++counter;
  221.             // reset counter to enforce periodicy
  222.             if (counter >= signal_length){
  223.                 counter = 0;
  224.                 ++cycle_count;
  225.             }
  226.         } else {
  227.  
  228.                 EPWM1A = 0;
  229.    
  230.             int16_t force = receive_measurement();
  231.             int32_t input_signal = shmem.signal[counter];  
  232.                 int32_t output_signal = 0;      
  233.             send_message( ++id,force , input_signal,output_signal,cycle_count,counter,signal_length);
  234.         }
  235.     }    
  236. }
  237.  
  238.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement