Using CAN bus with (not just NUCLEO) mbed boards

Dependencies:   mbed CANMsg

Committer:
alflind
Date:
Thu Apr 02 11:42:45 2020 +0000
Revision:
10:4b0101c6763c
Parent:
9:3211e88e30a5
Hello;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hudakz 0:1b9561cd1c36 1 /*
hudakz 1:6f8ffb2c2dd7 2 * An example showing how to use the mbed CAN API:
hudakz 0:1b9561cd1c36 3 *
hudakz 3:87a128bca8f5 4 * Two affordable (about $2 on ebay) STM32F103C8T6 boards (20kB SRAM, 64kB Flash),
hudakz 1:6f8ffb2c2dd7 5 * (see [https://developer.mbed.org/users/hudakz/code/STM32F103C8T6_Hello/] for more details)
hudakz 0:1b9561cd1c36 6 * are connected to the same CAN bus via transceivers (MCP2551 or TJA1040, or etc.).
hudakz 0:1b9561cd1c36 7 * CAN transceivers are not part of NUCLEO boards, therefore must be added by you.
hudakz 0:1b9561cd1c36 8 * Remember also that CAN bus (even a short one) must be terminated with 120 Ohm resitors at both ends.
hudakz 1:6f8ffb2c2dd7 9 *
hudakz 0:1b9561cd1c36 10 *
hudakz 1:6f8ffb2c2dd7 11 * The same code is used for both mbed boards, but:
hudakz 0:1b9561cd1c36 12 * For board #1 compile the example without any change.
hudakz 3:87a128bca8f5 13 * For board #2 comment out line 21 before compiling
hudakz 0:1b9561cd1c36 14 *
hudakz 3:87a128bca8f5 15 * Once the binaries have been downloaded to the boards reset both boards at the same time.
hudakz 0:1b9561cd1c36 16 *
hudakz 0:1b9561cd1c36 17 */
hudakz 1:6f8ffb2c2dd7 18
hudakz 8:c65afde7f7f5 19 //#define TARGET_STM32F103C8T6 1 // uncomment this line to use STM32F103C8T6 boards
hudakz 4:09d564da0e24 20
hudakz 4:09d564da0e24 21 #define BOARD1 1 // comment out this line when compiling for board #2
hudakz 0:1b9561cd1c36 22
hudakz 0:1b9561cd1c36 23 #if defined(TARGET_STM32F103C8T6)
hudakz 7:883da97339ab 24 #define LED_PIN PC_13
hudakz 7:883da97339ab 25 const int OFF = 1;
hudakz 7:883da97339ab 26 const int ON = 0;
hudakz 0:1b9561cd1c36 27 #else
hudakz 7:883da97339ab 28 #define LED_PIN LED1
hudakz 7:883da97339ab 29 const int OFF = 0;
hudakz 7:883da97339ab 30 const int ON = 1;
hudakz 0:1b9561cd1c36 31 #endif
hudakz 7:883da97339ab 32
hudakz 0:1b9561cd1c36 33 #if defined(BOARD1)
hudakz 7:883da97339ab 34 const unsigned int RX_ID = 0x100;
hudakz 7:883da97339ab 35 const unsigned int TX_ID = 0x101;
alflind 10:4b0101c6763c 36
hudakz 0:1b9561cd1c36 37 #else
alflind 10:4b0101c6763c 38
hudakz 7:883da97339ab 39 const unsigned int RX_ID = 0x101;
hudakz 7:883da97339ab 40 const unsigned int TX_ID = 0x100;
hudakz 0:1b9561cd1c36 41 #endif
hudakz 7:883da97339ab 42
hudakz 0:1b9561cd1c36 43 #include "mbed.h"
hudakz 0:1b9561cd1c36 44 #include "CANMsg.h"
hudakz 0:1b9561cd1c36 45
alflind 10:4b0101c6763c 46 //Serial pc(USBTX, USBRX);
alflind 10:4b0101c6763c 47 Serial pc(SERIAL_TX, SERIAL_RX);
hudakz 4:09d564da0e24 48 CAN can(PB_8, PB_9); // CAN Rx pin name, CAN Tx pin name
alflind 10:4b0101c6763c 49 //CAN can(PA_11, PA_12); // Use for RC-car
alflind 10:4b0101c6763c 50 DigitalIn button(PC_13);
hudakz 9:3211e88e30a5 51 //CAN can(p30, p29); // CAN Rx pin name, CAN Tx pin name
hudakz 0:1b9561cd1c36 52 CANMsg rxMsg;
hudakz 0:1b9561cd1c36 53 CANMsg txMsg;
hudakz 0:1b9561cd1c36 54 DigitalOut led(LED_PIN);
hudakz 0:1b9561cd1c36 55 Timer timer;
hudakz 0:1b9561cd1c36 56 uint8_t counter = 0;
hudakz 0:1b9561cd1c36 57 AnalogIn analogIn(A0);
hudakz 0:1b9561cd1c36 58 float voltage;
alflind 10:4b0101c6763c 59 char message;
alflind 10:4b0101c6763c 60 bool LED;
alflind 10:4b0101c6763c 61 bool brake;
alflind 10:4b0101c6763c 62 float a;
alflind 10:4b0101c6763c 63 float b;
alflind 10:4b0101c6763c 64 char c;
alflind 10:4b0101c6763c 65 float mid = 0.5;
alflind 10:4b0101c6763c 66 float p_DC = 0.05;
alflind 10:4b0101c6763c 67 float p_Servo= 0.05;
hudakz 0:1b9561cd1c36 68
hudakz 0:1b9561cd1c36 69 /**
hudakz 8:c65afde7f7f5 70 * @brief Prints CAN message to PC's serial terminal
hudakz 2:6546e4a2d593 71 * @note
hudakz 1:6f8ffb2c2dd7 72 * @param CANMessage to print
hudakz 3:87a128bca8f5 73 * @retval
hudakz 0:1b9561cd1c36 74 */
hudakz 5:37ab4112d547 75 void printMsg(CANMessage& msg)
hudakz 5:37ab4112d547 76 {
hudakz 0:1b9561cd1c36 77 pc.printf(" ID = 0x%.3x\r\n", msg.id);
hudakz 0:1b9561cd1c36 78 pc.printf(" Type = %d\r\n", msg.type);
hudakz 0:1b9561cd1c36 79 pc.printf(" Format = %d\r\n", msg.format);
hudakz 0:1b9561cd1c36 80 pc.printf(" Length = %d\r\n", msg.len);
hudakz 0:1b9561cd1c36 81 pc.printf(" Data =");
hudakz 0:1b9561cd1c36 82 for(int i = 0; i < msg.len; i++)
hudakz 0:1b9561cd1c36 83 pc.printf(" 0x%.2X", msg.data[i]);
hudakz 0:1b9561cd1c36 84 pc.printf("\r\n");
hudakz 0:1b9561cd1c36 85 }
hudakz 0:1b9561cd1c36 86
alflind 10:4b0101c6763c 87 float decodeTurn(char c, float floatA){
alflind 10:4b0101c6763c 88 a=floatA;
alflind 10:4b0101c6763c 89 switch (c){
alflind 10:4b0101c6763c 90 case 'l':
alflind 10:4b0101c6763c 91 c = '\0';
alflind 10:4b0101c6763c 92 if (LED == false){
alflind 10:4b0101c6763c 93 pc.printf("LED ON\n");
alflind 10:4b0101c6763c 94 led = 1;
alflind 10:4b0101c6763c 95 LED = true;
alflind 10:4b0101c6763c 96 }
alflind 10:4b0101c6763c 97 else {
alflind 10:4b0101c6763c 98 pc.printf("LED OFF\n");
alflind 10:4b0101c6763c 99 led = 0;
alflind 10:4b0101c6763c 100 LED = false;
alflind 10:4b0101c6763c 101 }
alflind 10:4b0101c6763c 102 break;
alflind 10:4b0101c6763c 103
alflind 10:4b0101c6763c 104 case 'q':
alflind 10:4b0101c6763c 105 c = '\0';
alflind 10:4b0101c6763c 106 led = 0; // OFF
alflind 10:4b0101c6763c 107 a = 0;
alflind 10:4b0101c6763c 108 pc.printf("Hard right %f \r\n",a);
alflind 10:4b0101c6763c 109 //moveTurnServo(a);
alflind 10:4b0101c6763c 110 break;
alflind 10:4b0101c6763c 111
alflind 10:4b0101c6763c 112 case 'e':
alflind 10:4b0101c6763c 113 c = '\0';
alflind 10:4b0101c6763c 114 led = 1; // ON
alflind 10:4b0101c6763c 115 a = 1;
alflind 10:4b0101c6763c 116 pc.printf("Hard right %f \r\n",a);
alflind 10:4b0101c6763c 117 //moveTurnServo(a);
alflind 10:4b0101c6763c 118 break;
alflind 10:4b0101c6763c 119
alflind 10:4b0101c6763c 120 case 'r':
alflind 10:4b0101c6763c 121 c = '\0';
alflind 10:4b0101c6763c 122 a=mid;
alflind 10:4b0101c6763c 123 pc.printf("Straightening up %f \r\n",a);
alflind 10:4b0101c6763c 124 //moveTurnServo(a);
alflind 10:4b0101c6763c 125 break;
alflind 10:4b0101c6763c 126
alflind 10:4b0101c6763c 127 case 'a':
alflind 10:4b0101c6763c 128 c = '\0';
alflind 10:4b0101c6763c 129 if(a > 0){
alflind 10:4b0101c6763c 130 a = a - p_Servo;
alflind 10:4b0101c6763c 131 pc.printf("Turning left %f \r\n",a);
alflind 10:4b0101c6763c 132 //moveTurnServo(a);
alflind 10:4b0101c6763c 133 }
alflind 10:4b0101c6763c 134 else{
alflind 10:4b0101c6763c 135 pc.printf("Servo at max left");
alflind 10:4b0101c6763c 136 }
alflind 10:4b0101c6763c 137 break;
alflind 10:4b0101c6763c 138
alflind 10:4b0101c6763c 139 case 'd':
alflind 10:4b0101c6763c 140 c = '\0';
alflind 10:4b0101c6763c 141 if(a < 1){
alflind 10:4b0101c6763c 142 a = a + p_Servo;
alflind 10:4b0101c6763c 143 pc.printf("Turning right %f \r\n",a);
alflind 10:4b0101c6763c 144 //moveTurnServo(a);
alflind 10:4b0101c6763c 145 }
alflind 10:4b0101c6763c 146 else{
alflind 10:4b0101c6763c 147 pc.printf("Servo at max right");
alflind 10:4b0101c6763c 148 }
alflind 10:4b0101c6763c 149 break;
alflind 10:4b0101c6763c 150
alflind 10:4b0101c6763c 151
alflind 10:4b0101c6763c 152 }
alflind 10:4b0101c6763c 153 return a;
alflind 10:4b0101c6763c 154 }
alflind 10:4b0101c6763c 155
alflind 10:4b0101c6763c 156 float decodeDC(char c, float floatB){
alflind 10:4b0101c6763c 157 b=floatB;
alflind 10:4b0101c6763c 158 switch (c){
alflind 10:4b0101c6763c 159 case 'w':
alflind 10:4b0101c6763c 160 c = '\0';
alflind 10:4b0101c6763c 161 if(b < 1){
alflind 10:4b0101c6763c 162 b = b + p_DC;
alflind 10:4b0101c6763c 163 pc.printf("Accelerating %f \r\n",b);
alflind 10:4b0101c6763c 164 //speedDCMotor(b);
alflind 10:4b0101c6763c 165 }
alflind 10:4b0101c6763c 166 else{
alflind 10:4b0101c6763c 167 pc.printf("Motor at max power");
alflind 10:4b0101c6763c 168 }
alflind 10:4b0101c6763c 169 break;
alflind 10:4b0101c6763c 170
alflind 10:4b0101c6763c 171 case 's':
alflind 10:4b0101c6763c 172 c = '\0';
alflind 10:4b0101c6763c 173 if(b > 0){
alflind 10:4b0101c6763c 174 b = b - p_DC;
alflind 10:4b0101c6763c 175 pc.printf("Deaccelerating %f \r\n",b);
alflind 10:4b0101c6763c 176 //speedDCMotor(b);
alflind 10:4b0101c6763c 177 }
alflind 10:4b0101c6763c 178 else{
alflind 10:4b0101c6763c 179 pc.printf("Motor at max power");
alflind 10:4b0101c6763c 180 }
alflind 10:4b0101c6763c 181 break;
alflind 10:4b0101c6763c 182
alflind 10:4b0101c6763c 183 case 'f':
alflind 10:4b0101c6763c 184 c = '\0';
alflind 10:4b0101c6763c 185 b = mid;
alflind 10:4b0101c6763c 186 pc.printf("Stopping DC Motor %f \r\n",b);
alflind 10:4b0101c6763c 187 //speedDCMotor(b);
alflind 10:4b0101c6763c 188 break;
alflind 10:4b0101c6763c 189
alflind 10:4b0101c6763c 190 case 'b':
alflind 10:4b0101c6763c 191 c = '\0';
alflind 10:4b0101c6763c 192 if (brake == false){
alflind 10:4b0101c6763c 193 pc.printf("Breaking\n");
alflind 10:4b0101c6763c 194 //moveBrakeServo(1);
alflind 10:4b0101c6763c 195 brake = true;
alflind 10:4b0101c6763c 196 }
alflind 10:4b0101c6763c 197 else {
alflind 10:4b0101c6763c 198 pc.printf("Releasing breaking\n");
alflind 10:4b0101c6763c 199 //moveBrakeServo(mid);
alflind 10:4b0101c6763c 200 brake = false;
alflind 10:4b0101c6763c 201 }
alflind 10:4b0101c6763c 202 }
alflind 10:4b0101c6763c 203 return b;
alflind 10:4b0101c6763c 204 }
alflind 10:4b0101c6763c 205
alflind 10:4b0101c6763c 206
hudakz 0:1b9561cd1c36 207 /**
hudakz 5:37ab4112d547 208 * @brief Handles received CAN messages
hudakz 8:c65afde7f7f5 209 * @note Called on 'CAN message received' interrupt.
hudakz 5:37ab4112d547 210 * @param
hudakz 5:37ab4112d547 211 * @retval
hudakz 5:37ab4112d547 212 */
hudakz 5:37ab4112d547 213 void onCanReceived(void)
hudakz 5:37ab4112d547 214 {
hudakz 5:37ab4112d547 215 can.read(rxMsg);
hudakz 9:3211e88e30a5 216 pc.printf("-------------------------------------\r\n");
hudakz 9:3211e88e30a5 217 pc.printf("CAN message received\r\n");
hudakz 5:37ab4112d547 218 printMsg(rxMsg);
hudakz 5:37ab4112d547 219
hudakz 5:37ab4112d547 220 if (rxMsg.id == RX_ID) {
hudakz 5:37ab4112d547 221 // extract data from the received CAN message
hudakz 8:c65afde7f7f5 222 // in the same order as it was added on the transmitter side
hudakz 5:37ab4112d547 223 rxMsg >> counter;
alflind 10:4b0101c6763c 224 rxMsg >> voltage;
alflind 10:4b0101c6763c 225 txMsg << message;
hudakz 5:37ab4112d547 226 pc.printf(" counter = %d\r\n", counter);
hudakz 5:37ab4112d547 227 pc.printf(" voltage = %e V\r\n", voltage);
alflind 10:4b0101c6763c 228 pc.printf(" message = %s \r\n", message);
hudakz 5:37ab4112d547 229 }
hudakz 8:c65afde7f7f5 230 timer.start(); // to transmit next message in main
alflind 10:4b0101c6763c 231 pc.printf("-------------------------------------\r\n");
hudakz 5:37ab4112d547 232 }
hudakz 5:37ab4112d547 233
hudakz 5:37ab4112d547 234
hudakz 5:37ab4112d547 235 /**
hudakz 0:1b9561cd1c36 236 * @brief Main
hudakz 0:1b9561cd1c36 237 * @note
hudakz 0:1b9561cd1c36 238 * @param
hudakz 0:1b9561cd1c36 239 * @retval
hudakz 0:1b9561cd1c36 240 */
hudakz 0:1b9561cd1c36 241 int main(void)
alflind 10:4b0101c6763c 242 {
alflind 10:4b0101c6763c 243 a = mid;
alflind 10:4b0101c6763c 244 b = mid;
hudakz 8:c65afde7f7f5 245 pc.baud(9600); // set serial speed
hudakz 8:c65afde7f7f5 246 can.frequency(1000000); // set CAN bit rate to 1Mbps
hudakz 5:37ab4112d547 247 can.filter(RX_ID, 0xFFF, CANStandard, 0); // set filter #0 to accept only standard messages with ID == RX_ID
hudakz 8:c65afde7f7f5 248 can.attach(onCanReceived); // attach ISR to handle received messages
hudakz 1:6f8ffb2c2dd7 249 led = ON; // turn the LED on
hudakz 1:6f8ffb2c2dd7 250 timer.start(); // start timer
hudakz 1:6f8ffb2c2dd7 251 pc.printf("CAN_Hello board #1\r\n");
alflind 10:4b0101c6763c 252
hudakz 0:1b9561cd1c36 253 while(1) {
alflind 10:4b0101c6763c 254 c = pc.getc(); // Read hyperterminal1
alflind 10:4b0101c6763c 255 a = decodeTurn(c,a);
alflind 10:4b0101c6763c 256 b = decodeDC(c,b);
alflind 10:4b0101c6763c 257 pc.printf("a %f \r\n",a);
alflind 10:4b0101c6763c 258 pc.printf("Pressed %c \r\n",c);
alflind 10:4b0101c6763c 259 if(!button){
alflind 10:4b0101c6763c 260 led = 1; // ON
alflind 10:4b0101c6763c 261 wait(0.05);
alflind 10:4b0101c6763c 262 led = 0; // ON
alflind 10:4b0101c6763c 263 wait(0.05);
alflind 10:4b0101c6763c 264 }
alflind 10:4b0101c6763c 265
alflind 10:4b0101c6763c 266 if(timer.read_ms() >= 200) { // check for timeout
hudakz 3:87a128bca8f5 267 timer.stop(); // stop timer
hudakz 3:87a128bca8f5 268 timer.reset(); // reset timer
hudakz 3:87a128bca8f5 269 counter++; // increment counter
hudakz 5:37ab4112d547 270 voltage = analogIn * 3.3f; // read the small drift voltage from analog input
alflind 10:4b0101c6763c 271 voltage = a;
hudakz 3:87a128bca8f5 272 txMsg.clear(); // clear Tx message storage
hudakz 3:87a128bca8f5 273 txMsg.id = TX_ID; // set ID
hudakz 5:37ab4112d547 274 // append data (total data length must not exceed 8 bytes!)
hudakz 5:37ab4112d547 275 txMsg << counter; // one byte
hudakz 5:37ab4112d547 276 txMsg << voltage; // four bytes
alflind 10:4b0101c6763c 277 txMsg << message; // bytes
hudakz 5:37ab4112d547 278
hudakz 3:87a128bca8f5 279 if(can.write(txMsg)) { // transmit message
hudakz 3:87a128bca8f5 280 led = OFF; // turn the LED off
hudakz 0:1b9561cd1c36 281 pc.printf("-------------------------------------\r\n");
hudakz 9:3211e88e30a5 282 pc.printf("-------------------------------------\r\n");
hudakz 0:1b9561cd1c36 283 pc.printf("CAN message sent\r\n");
hudakz 0:1b9561cd1c36 284 printMsg(txMsg);
hudakz 0:1b9561cd1c36 285 pc.printf(" counter = %d\r\n", counter);
alflind 10:4b0101c6763c 286 pc.printf(" value = %e \r\n", voltage);
alflind 10:4b0101c6763c 287 pc.printf(" message = %s \r\n", message);
hudakz 0:1b9561cd1c36 288 }
hudakz 0:1b9561cd1c36 289 else
hudakz 0:1b9561cd1c36 290 pc.printf("Transmission error\r\n");
alflind 10:4b0101c6763c 291 pc.printf("-------------------------------------\r\n");
hudakz 0:1b9561cd1c36 292 }
alflind 10:4b0101c6763c 293 //timer.start(); // start timer
hudakz 0:1b9561cd1c36 294 }
hudakz 0:1b9561cd1c36 295 }