Mangue Baja team's code to rear ECU

main.cpp

Committer:
einsteingustavo
Date:
2019-07-24
Revision:
0:80950b84a6c4

File content as of revision 0:80950b84a6c4:

#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;
    }
}