Mangue Baja team's code to rear ECU

Revision:
0:80950b84a6c4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Jul 24 20:04:55 2019 +0000
@@ -0,0 +1,370 @@
+#include "mbed.h"
+#include "stats_report.h"
+/* User libraries */
+#include "definitions.h"
+#include "reardefs.h"
+#include "CANMsg.h"
+#include "RFM69.h"
+
+#define MB1                 // uncomment this line if MB1
+//#define MB2                 // uncomment this line if MB2
+
+#ifdef MB1
+    #define NODE_ID MB1_ID
+#endif
+#ifdef MB2
+    #define NODE_ID MB2_ID
+#endif
+
+/* Communication protocols */
+CAN can(PB_8, PB_9, 1000000);
+Serial serial(PA_2, PA_3, 115200); 
+RFM69 radio(PB_15, PB_14, PB_13, PB_12, PA_8); // RFM69::RFM69(PinName  PinName mosi, PinName miso, PinName sclk,slaveSelectPin, PinName int)
+/* I/O pins */
+AnalogIn analog(PA_0);
+#ifdef MB1
+DigitalIn fuel_sensor(PB_5, PullNone);                                          // MB2
+InterruptIn freq_sensor(PB_4, PullNone);                                        // MB2
+#endif
+#ifdef MB2
+DigitalIn fuel_sensor(PB_6, PullNone);                                          // MB2
+InterruptIn freq_sensor(PB_5, PullNone);                                        // MB2
+#endif
+PwmOut servo(PA_6);
+/* Debug pins */
+PwmOut signal(PA_7);
+DigitalOut led(PC_13);
+DigitalOut dbg1(PC_14);
+DigitalOut dbg2(PC_15);
+DigitalOut dbg3(PA_1);
+DigitalOut dbg4(PA_4);
+/* Interrupt services routine */
+void canISR();
+void servoSwitchISR();
+void ticker1HzISR();
+void ticker5HzISR();
+void ticker100HzISR();
+void frequencyCounterISR();
+/* Interrupt handlers */
+void canHandler();
+/* General functions*/
+void initPWM();
+void initRadio();
+void setupInterrupts();
+void filterMessage(CANMsg msg);
+void writeServo(uint8_t state);
+
+/* Debug variables */
+Timer t;
+Timer engine_counter; 
+bool buffer_full = false;
+uint32_t tim1, tim2, imu_last_acq = 0;
+
+/* Mbed OS tools */
+Thread eventThread;
+EventQueue queue(1024);
+Ticker ticker1Hz;
+Ticker ticker5Hz;
+Ticker ticker100Hz;
+Timeout fuel_timeout;
+CircularBuffer <state_t, 2*BUFFER_SIZE> state_buffer;
+CircularBuffer <imu_t*, 20> imu_buffer;
+
+/* Global variables */
+bool switch_clicked = false;
+uint8_t switch_state = 0x00;
+state_t current_state = IDLE_ST;
+uint8_t pulse_counter = 0;
+uint64_t current_period = 0, last_count = 0;
+float rpm_hz, V_termistor = 0;
+uint8_t fuel_timer = 0;
+uint8_t fuel_counter = 0;
+bool box = false;
+packet_t data;                                // Create package for radio comunication
+uint8_t imu_counter;
+
+int main()
+{
+    /* Main variables */
+    CANMsg txMsg;
+    /* Initialization */
+    t.start();
+    eventThread.start(callback(&queue, &EventQueue::dispatch_forever));
+    initPWM();
+    initRadio();
+    setupInterrupts();
+    
+    while (true) {
+        if (state_buffer.full())
+        {
+            buffer_full = true;
+            led = 0;
+        }    
+        else
+        {
+            led = 1;
+            buffer_full = false;
+            if (!state_buffer.empty())
+                state_buffer.pop(current_state);
+            else
+                current_state = IDLE_ST;
+        }
+
+        switch (current_state)
+        {   
+            case IDLE_ST:
+//              Thread::wait(1);
+                break;
+            case TEMP_ST:
+                //serial.printf("t");
+                dbg1 = 0;
+                V_termistor = VCC*analog.read();
+                data.temperature = ((float) (1.0/0.032)*log((1842.8*(VCC - V_termistor)/(V_termistor*R_TERM))));
+                /* Send temperature data */
+                txMsg.clear(TEMPERATURE_ID);
+                txMsg << data.temperature;
+                can.write(txMsg);
+                break;
+            case FUEL_ST:
+                //serial.printf("f");
+                data.flags &= ~(0x88);                             // clear fuel and box flags
+                data.flags |= (fuel_counter > NORMAL_THRESHOLD) ? (0x01 << 3) : 0;
+                data.flags |= box << 7;
+                
+                txMsg.clear(FLAGS_ID);
+                txMsg << data.flags;
+                can.write(txMsg);
+
+                fuel_timer = 0;
+                fuel_counter = 0;
+                ticker100Hz.attach(&ticker100HzISR, 0.01);
+                dbg1 = 0;
+                break;
+            case RPM_ST:
+                //serial.printf("r");
+                dbg2 = 1;
+                freq_sensor.fall(NULL);         // disable interrupt
+                if (current_period != 0)
+                {
+                    rpm_hz = ((float)pulse_counter/(current_period/1000000.0));    //calculates frequency in Hz
+                    if (switch_state != RUN_MODE)
+                        writeServo(RUN_MODE);
+//                    engine_counter.start();
+                }
+                else
+                {
+                    rpm_hz = 0;
+                    writeServo(switch_state);
+//                    engine_counter.stop();
+                }
+                /* Send rpm data */
+                txMsg.clear(RPM_ID);
+                txMsg << ((uint16_t) rpm_hz);
+                can.write(txMsg);
+                /* prepare to re-init rpm counter */
+                pulse_counter = 0;                          
+                current_period = 0;                                   // reset pulses related variables
+                last_count = t.read_us();        
+                freq_sensor.fall(&frequencyCounterISR);               // enable interrupt
+                
+                dbg2 = 0;
+                break;
+            case THROTTLE_ST:
+                if (switch_clicked)
+                {
+                    writeServo(switch_state);
+                    switch_clicked = false;
+                }
+
+                break;
+            case RADIO_ST:
+                imu_t* temp_imu;
+//                dbg4 = 1; 
+                //if(radio.receiveDone())
+//                {
+//                    if (radio.ACKRequested())
+//                        radio.sendACK();
+//                    led = 0;
+//                    box = (bool) radio.DATA;
+////                    serial.printf("%d\r\n", (bool)radio.DATA);
+//                }
+                
+//                serial.printf("%d,%d,%d\r\n", (!imu_buffer.empty()), (!d10hz_buffer.empty()), (!temp_buffer.empty()));
+//                if((!imu_buffer.empty()) && (!d10hz_buffer.empty()) && (!temp_buffer.empty()))
+//                {
+                    if (!imu_buffer.empty())
+                    {
+                        imu_buffer.pop(temp_imu);
+                        memcpy(&data.imu, temp_imu, 4*sizeof(imu_t));
+                        data.rpm = ((uint16_t)rpm_hz * 60)*65536.0/5000.0;
+                        radio.send((uint8_t)BOXRADIO_ID, &data, sizeof(packet_t), true, false);     // request ACK with 1 retry (waitTime = 40ms)
+                    }
+                    else if (t.read_ms() - imu_last_acq > 500)
+                    {
+                        memset(&data.imu, 0, 4*sizeof(imu_t));
+                        data.rpm = ((uint16_t)rpm_hz * 60)*65536.0/5000.0;
+                        radio.send((uint8_t)BOXRADIO_ID, &data, sizeof(packet_t), true, false);     // request ACK with 1 retry (waitTime = 40ms)
+                    }
+//                }
+//                radio.receiveDone();
+                dbg4 = 0;
+//                tim2 = t.read_us() - tim1;
+//                serial.printf("%d\r\n",tim2);
+                break;
+            case DEBUG_ST:
+//                serial.printf("radio state pushed");
+//                serial.printf("bf=%d, cr=%d\r\n", buffer_full, switch_state);
+//                serial.printf("speed=%d\r\n", data.data_10hz[packet_counter[N_SPEED]].speed);
+//                serial.printf("rpm=%d\r\n", data.data_10hz[packet_counter[N_RPM]].rpm);
+//                serial.printf("imu acc x =%d\r\n", data.imu[imu_counter].acc_x);
+//                serial.printf("imu acc y =%d\r\n", data.imu[imu_counter].acc_y);
+//                serial.printf("imu acc z =%d\r\n", data.imu[imu_counter].acc_z);
+//                serial.printf("imu dps x =%d\r\n", data.imu[imu_counter].dps_x);
+//                serial.printf("imu dps y =%d\r\n", data.imu[imu_counter].dps_y);
+//                serial.printf("imu dps z =%d\r\n", data.imu[imu_counter].dps_z);
+                break;
+            default:
+                break;
+        }
+    }
+}
+
+/* Interrupt services routine */
+void canISR()
+{
+    CAN_IER &= ~CAN_IER_FMPIE0;                 // disable RX interrupt
+    queue.call(&canHandler);                    // add canHandler() to events queue
+}
+
+void ticker1HzISR()
+{
+    state_buffer.push(TEMP_ST);
+}
+
+void ticker5HzISR()
+{
+    state_buffer.push(RPM_ST);
+    state_buffer.push(RADIO_ST);
+}
+
+void ticker100HzISR()
+{
+    if (fuel_timer < 100)
+    {
+        fuel_timer++;
+        fuel_counter += !fuel_sensor.read();
+    }
+    else
+    {
+        state_buffer.push(FUEL_ST);
+        ticker100Hz.detach();
+    }
+}
+
+void frequencyCounterISR()
+{
+    led = !led;
+    pulse_counter++;
+    current_period += t.read_us() - last_count;
+    last_count = t.read_us();      
+}
+
+/* Interrupt handlers */
+void canHandler()
+{
+    CANMsg rxMsg;
+
+    can.read(rxMsg);
+    filterMessage(rxMsg);
+    CAN_IER |= CAN_IER_FMPIE0;                  // enable RX interrupt
+}
+
+/* General functions */
+void initPWM()
+{
+    servo.period_ms(20);                        // set signal frequency to 50Hz
+    servo.write(0);                             // disables servo
+    signal.period_ms(32);                       // set signal frequency to 1/0.032Hz
+    signal.write(0.5f);                         // dutycycle 50%
+}
+
+void initRadio()
+{
+    radio.initialize(FREQUENCY_915MHZ, NODE_ID, NETWORK_ID);
+    radio.encrypt(0);
+    radio.setPowerLevel(20);
+}
+
+void setupInterrupts()
+{
+    can.attach(&canISR, CAN::RxIrq);
+    ticker1Hz.attach(&ticker1HzISR, 1.0);
+    ticker5Hz.attach(&ticker5HzISR, 0.2);
+    ticker100Hz.attach(&ticker100HzISR, 0.01);
+    freq_sensor.fall(&frequencyCounterISR);
+}
+
+void filterMessage(CANMsg msg)
+{
+    led = !led;
+    
+    if (msg.id == THROTTLE_ID)
+    {
+        switch_clicked = true;
+        state_buffer.push(THROTTLE_ST);
+        msg >> switch_state;
+    }
+    else if (msg.id == IMU_ACC_ID)
+    {
+        imu_last_acq = t.read_ms();
+        msg >> data.imu[imu_counter].acc_x >> data.imu[imu_counter].acc_y >> data.imu[imu_counter].acc_z;
+    }
+    else if (msg.id == IMU_DPS_ID)
+    {
+        msg >> data.imu[imu_counter].dps_x >> data.imu[imu_counter].dps_y
+                         >> data.imu[imu_counter].dps_z;
+        if (imu_counter < 3)
+        {
+            imu_counter++;
+        }
+        else if (imu_counter == 3)
+        {
+            imu_buffer.push(data.imu);
+            imu_counter = 0;
+        }
+    }
+    else if (msg.id == SPEED_ID)
+    {
+        msg >> data.speed;
+//      serial.printf("\r\nspeed = %d\r\n",data.data_10hz[packet_counter[N_SPEED]].speed);
+//      d10hz_buffer.push(data.data_10hz);
+    }
+}
+
+    void writeServo(uint8_t state)
+{
+    data.flags &= ~(0x07);         // reset servo-related flags
+
+    switch (state)
+    {
+        case MID_MODE:
+            dbg3 = !dbg3;
+            servo.pulsewidth_us(SERVO_MID);
+            data.flags &= ~(0x03); // reset run and choke flags
+            break;
+        case RUN_MODE:
+            dbg3 = !dbg3;
+            servo.pulsewidth_us(SERVO_RUN);
+            data.flags |= RUN_MODE;    // set run flag
+            break;
+        case CHOKE_MODE:
+            dbg3 = !dbg3;
+            servo.pulsewidth_us(SERVO_CHOKE);
+            data.flags |= CHOKE_MODE;    // set choke flag
+            break;
+        default:
+//            serial.printf("Choke/run error\r\n");
+            data.flags |= 0x04;    // set servo error flag
+            break;
+    }
+}