Using CAN bus with (not just NUCLEO) mbed boards

Dependencies:   mbed CANMsg

main.cpp

Committer:
alflind
Date:
2020-04-02
Revision:
10:4b0101c6763c
Parent:
9:3211e88e30a5

File content as of revision 10:4b0101c6763c:

/*
 * An example showing how to use the mbed CAN API:
 *
 * Two affordable (about $2 on ebay) STM32F103C8T6 boards (20kB SRAM, 64kB Flash),
 * (see [https://developer.mbed.org/users/hudakz/code/STM32F103C8T6_Hello/] for more details)
 * are connected to the same CAN bus via transceivers (MCP2551 or TJA1040, or etc.).
 * CAN transceivers are not part of NUCLEO boards, therefore must be added by you.
 * Remember also that CAN bus (even a short one) must be terminated with 120 Ohm resitors at both ends.
 *
 *
 * The same code is used for both mbed boards, but:
 *      For board #1 compile the example without any change.
 *      For board #2 comment out line 21 before compiling
 *
 * Once the binaries have been downloaded to the boards reset both boards at the same time.
 *
 */

//#define TARGET_STM32F103C8T6    1       // uncomment this line to use STM32F103C8T6 boards

#define BOARD1                  1       // comment out this line when compiling for board #2

#if defined(TARGET_STM32F103C8T6)
    #define LED_PIN     PC_13
    const int           OFF = 1;
    const int           ON = 0;
#else
    #define LED_PIN     LED1
    const int           OFF = 0;
    const int           ON = 1;
#endif

#if defined(BOARD1)
    const unsigned int  RX_ID = 0x100;
    const unsigned int  TX_ID = 0x101;
    
#else
    
    const unsigned int  RX_ID = 0x101;
    const unsigned int  TX_ID = 0x100;
#endif

#include "mbed.h"
#include "CANMsg.h"

//Serial              pc(USBTX, USBRX);
Serial              pc(SERIAL_TX, SERIAL_RX);
CAN                 can(PB_8, PB_9);  // CAN Rx pin name, CAN Tx pin name
//CAN                 can(PA_11, PA_12);  // Use for RC-car
DigitalIn           button(PC_13);
//CAN                 can(p30, p29);  // CAN Rx pin name, CAN Tx pin name
CANMsg              rxMsg;
CANMsg              txMsg;
DigitalOut          led(LED_PIN);
Timer               timer;
uint8_t             counter = 0;
AnalogIn            analogIn(A0);
float               voltage;
char                message;
bool                LED;
bool                brake;
float               a;
float               b;
char                c;
float               mid = 0.5;
float               p_DC = 0.05;
float               p_Servo= 0.05;

/**
 * @brief   Prints CAN message to PC's serial terminal
 * @note
 * @param   CANMessage to print
 * @retval
 */
void printMsg(CANMessage& msg)
{
    pc.printf("  ID      = 0x%.3x\r\n", msg.id);
    pc.printf("  Type    = %d\r\n", msg.type);
    pc.printf("  Format  = %d\r\n", msg.format);
    pc.printf("  Length  = %d\r\n", msg.len);
    pc.printf("  Data    =");
    for(int i = 0; i < msg.len; i++)
        pc.printf(" 0x%.2X", msg.data[i]);
    pc.printf("\r\n");
}

float decodeTurn(char c, float floatA){
        a=floatA;
        switch (c){
            case 'l':
                c  = '\0';
                if (LED == false){
                    pc.printf("LED ON\n");
                    led = 1;
                    LED = true;
                    }
                else {
                    pc.printf("LED OFF\n");
                    led = 0;
                    LED = false;
                    }
                break;               
                            
            case 'q':
                c = '\0';
                led = 0; // OFF
                a = 0;
                pc.printf("Hard right %f \r\n",a);
                //moveTurnServo(a);
                break;
            
            case 'e':
                c = '\0';
                led = 1; // ON
                a = 1;
                pc.printf("Hard right %f \r\n",a);
                //moveTurnServo(a);
                break;
                
            case 'r':
                c = '\0';
                a=mid;
                pc.printf("Straightening up %f \r\n",a);
                //moveTurnServo(a);
                break;
            
            case 'a':
                c = '\0';
                if(a > 0){
                    a = a - p_Servo;
                    pc.printf("Turning left %f \r\n",a);
                    //moveTurnServo(a);
                }
                else{
                    pc.printf("Servo at max left");
                    }
                break;
            
            case 'd':
                c = '\0';
                if(a < 1){
                    a = a + p_Servo;
                    pc.printf("Turning right %f \r\n",a);
                    //moveTurnServo(a);
                }
                else{
                    pc.printf("Servo at max right");
                    } 
                break;
    
                      
        }
        return a;
}

float decodeDC(char c, float floatB){
        b=floatB;
        switch (c){
            case 'w':
                c = '\0';
                if(b < 1){
                    b = b + p_DC;
                    pc.printf("Accelerating %f \r\n",b);
                    //speedDCMotor(b);
                }
                else{
                    pc.printf("Motor at max power");
                    }                
                break;
                
            case 's':
                c = '\0';
                if(b > 0){
                    b = b - p_DC;
                    pc.printf("Deaccelerating %f \r\n",b);
                    //speedDCMotor(b);
                }
                else{
                    pc.printf("Motor at max power");
                    } 
                break;
                
            case 'f':
                c = '\0'; 
                b = mid;
                pc.printf("Stopping DC Motor %f \r\n",b);
                //speedDCMotor(b);               
                break;
                
            case 'b':
                c  = '\0';
                if (brake == false){
                    pc.printf("Breaking\n");
                    //moveBrakeServo(1);
                    brake = true;
                    }
                else {
                    pc.printf("Releasing breaking\n");
                    //moveBrakeServo(mid);
                    brake = false;
                    }     
            }
            return b;
}
            

/**
 * @brief   Handles received CAN messages
 * @note    Called on 'CAN message received' interrupt.
 * @param
 * @retval
 */
void onCanReceived(void)
{
    can.read(rxMsg);
    pc.printf("-------------------------------------\r\n");
    pc.printf("CAN message received\r\n");
    printMsg(rxMsg);

    if (rxMsg.id == RX_ID) {
        // extract data from the received CAN message 
        // in the same order as it was added on the transmitter side
        rxMsg >> counter;
        rxMsg >> voltage;
        txMsg << message;    
        pc.printf("  counter = %d\r\n", counter);
        pc.printf("  voltage = %e V\r\n", voltage);
        pc.printf("  message = %s \r\n", message);
    }
    timer.start(); // to transmit next message in main
    pc.printf("-------------------------------------\r\n");
}


/**
 * @brief   Main
 * @note
 * @param
 * @retval
 */
int main(void)
{   
    a = mid;
    b = mid;
    pc.baud(9600);          // set serial speed
    can.frequency(1000000); // set CAN bit rate to 1Mbps
    can.filter(RX_ID, 0xFFF, CANStandard, 0); // set filter #0 to accept only standard messages with ID == RX_ID
    can.attach(onCanReceived);                // attach ISR to handle received messages
    led = ON;               // turn the LED on
    timer.start();          // start timer
    pc.printf("CAN_Hello board #1\r\n");
    
    while(1) {
        c = pc.getc(); // Read hyperterminal1
        a = decodeTurn(c,a);
        b = decodeDC(c,b);
        pc.printf("a %f \r\n",a);
        pc.printf("Pressed %c \r\n",c);
        if(!button){
            led = 1; // ON
            wait(0.05);
            led = 0; // ON
            wait(0.05);
            }
            
        if(timer.read_ms() >= 200) {    // check for timeout
            timer.stop();                // stop timer
            timer.reset();               // reset timer
            counter++;                   // increment counter
            voltage = analogIn * 3.3f;   // read the small drift voltage from analog input
            voltage = a;
            txMsg.clear();               // clear Tx message storage
            txMsg.id = TX_ID;            // set ID
            // append data (total data length must not exceed 8 bytes!)
            txMsg << counter;   // one byte
            txMsg << voltage;   // four bytes
            txMsg << message;   //  bytes
             
            if(can.write(txMsg)) {       // transmit message
                led = OFF;               // turn the LED off
                pc.printf("-------------------------------------\r\n");
                pc.printf("-------------------------------------\r\n");
                pc.printf("CAN message sent\r\n");
                printMsg(txMsg);
                pc.printf("  counter = %d\r\n", counter);
                pc.printf("  value = %e \r\n", voltage);
                pc.printf("  message = %s \r\n", message);
            }
            else
                pc.printf("Transmission error\r\n");
            pc.printf("-------------------------------------\r\n");
        }
        //timer.start();          // start timer
    }
}