diff --git a/src/bobbycar-protocol b/src/bobbycar-protocol index 994d0c9..fee1175 160000 --- a/src/bobbycar-protocol +++ b/src/bobbycar-protocol @@ -1 +1 @@ -Subproject commit 994d0c95a72ed8e42a6875f771c778481073d470 +Subproject commit fee1175bf819826222086aa1e3c7fbb66d37a33c diff --git a/src/can.h b/src/can.h index 2c38126..3de55ed 100644 --- a/src/can.h +++ b/src/can.h @@ -1,5 +1,7 @@ #pragma once +#include + #include #include #include @@ -12,11 +14,9 @@ #include "globals.h" namespace { -millis_t m_lastCanFeedback{}; - void initCan() { - Serial.printf("CAN info hello world\r\n"); + Serial.println("initCan()"); can_general_config_t g_config = CAN_GENERAL_CONFIG_DEFAULT(GPIO_NUM_21, GPIO_NUM_22, CAN_MODE_NORMAL); can_timing_config_t t_config CAN_TIMING_CONFIG_250KBITS(); @@ -59,100 +59,222 @@ void initCan() } } -void parseCanInput() +template +bool parseCanMessage(const can_message_t &message) { - can_message_t message; - if (const auto result = can_receive(&message, pdMS_TO_TICKS(200)); result != ESP_OK) - { - controllers.front.feedbackValid = millis() - m_lastCanFeedback <= 100; - - if (result != ESP_ERR_TIMEOUT) - Serial.printf("CAN err can_receive() failed with %s\r\n", esp_err_to_name(result)); - return; - } + auto &controller = isBack ? controllers.back : controllers.front; switch (message.identifier) { - case MotorControllerFrontLeftDcLink: - m_lastCanFeedback = millis(); - controllers.front.feedbackValid = true; - controllers.front.feedback.left.current = *((int16_t*)message.data); - break; - case MotorControllerFrontRightDcLink: - m_lastCanFeedback = millis(); - controllers.front.feedbackValid = true; - controllers.front.feedback.right.current = *((int16_t*)message.data); - break; - case MotorControllerFrontLeftSpeed: - m_lastCanFeedback = millis(); - controllers.front.feedbackValid = true; - controllers.front.feedback.left.speed = *((int16_t*)message.data); - break; - case MotorControllerFrontRightSpeed: - m_lastCanFeedback = millis(); - controllers.front.feedbackValid = true; - controllers.front.feedback.right.speed = *((int16_t*)message.data); - break; - case MotorControllerFrontLeftError: - m_lastCanFeedback = millis(); - controllers.front.feedbackValid = true; - controllers.front.feedback.left.error = *((int8_t*)message.data); - break; - case MotorControllerFrontRightError: - m_lastCanFeedback = millis(); - controllers.front.feedbackValid = true; - controllers.front.feedback.right.error = *((int8_t*)message.data); - break; - case MotorControllerFrontLeftAngle: - m_lastCanFeedback = millis(); - controllers.front.feedbackValid = true; - controllers.front.feedback.left.angle = *((int16_t*)message.data); - break; - case MotorControllerFrontRightAngle: - m_lastCanFeedback = millis(); - controllers.front.feedbackValid = true; - controllers.front.feedback.right.angle = *((int16_t*)message.data); - break; - case MotorControllerFrontLeftChops: - m_lastCanFeedback = millis(); - controllers.front.feedbackValid = true; - controllers.front.feedback.left.chops = *((uint16_t*)message.data); - break; - case MotorControllerFrontRightChops: - m_lastCanFeedback = millis(); - controllers.front.feedbackValid = true; - controllers.front.feedback.right.chops = *((uint16_t*)message.data); - break; - case MotorControllerFrontLeftHall: - { - m_lastCanFeedback = millis(); - controllers.front.feedbackValid = true; - controllers.front.feedback.left.hallA = *((uint8_t*)message.data) & 1; - controllers.front.feedback.left.hallB = *((uint8_t*)message.data) & 2; - controllers.front.feedback.left.hallC = *((uint8_t*)message.data) & 4; - break; + using namespace bobbycar::can; + case MotorController::Feedback::DcLink: + controller.feedback.left.current = *((int16_t*)message.data); + return true; + case MotorController::Feedback::DcLink: + controller.feedback.right.current = *((int16_t*)message.data); + return true; + case MotorController::Feedback::Speed: + controller.feedback.left.speed = *((int16_t*)message.data); + return true; + case MotorController::Feedback::Speed: + controller.feedback.right.speed = *((int16_t*)message.data); + return true; + case MotorController::Feedback::Error: + controller.feedback.left.error = *((int8_t*)message.data); + return true; + case MotorController::Feedback::Error: + controller.feedback.right.error = *((int8_t*)message.data); + return true; + case MotorController::Feedback::Angle: + controller.feedback.left.angle = *((int16_t*)message.data); + return true; + case MotorController::Feedback::Angle: + controller.feedback.right.angle = *((int16_t*)message.data); + return true; + case MotorController::Feedback::DcPhaA: + case MotorController::Feedback::DcPhaA: + case MotorController::Feedback::DcPhaB: + case MotorController::Feedback::DcPhaB: + case MotorController::Feedback::DcPhaC: + case MotorController::Feedback::DcPhaC: + return true; + case MotorController::Feedback::Chops: + controller.feedback.left.chops = *((uint16_t*)message.data); + return true; + case MotorController::Feedback::Chops: + controller.feedback.right.chops = *((uint16_t*)message.data); + return true; + case MotorController::Feedback::Hall: + controller.feedback.left.hallA = *((uint8_t*)message.data) & 1; + controller.feedback.left.hallB = *((uint8_t*)message.data) & 2; + controller.feedback.left.hallC = *((uint8_t*)message.data) & 4; + return true; + case MotorController::Feedback::Hall: + controller.feedback.right.hallA = *((uint8_t*)message.data) & 1; + controller.feedback.right.hallB = *((uint8_t*)message.data) & 2; + controller.feedback.right.hallC = *((uint8_t*)message.data) & 4; + return true; + case MotorController::Feedback::Voltage: + case MotorController::Feedback::Voltage: + controller.feedback.batVoltage = *((int16_t*)message.data); + return true; + case MotorController::Feedback::Temp: + case MotorController::Feedback::Temp: + controller.feedback.boardTemp = *((int16_t*)message.data); + return true; } - case MotorControllerFrontRightHall: + + return false; +} + +bool parseCanInput() +{ + can_message_t message; + if (const auto result = can_receive(&message, pdMS_TO_TICKS(50)); result != ESP_OK) { - m_lastCanFeedback = millis(); - controllers.front.feedbackValid = true; - controllers.front.feedback.right.hallA = *((uint8_t*)message.data) & 1; - controllers.front.feedback.right.hallB = *((uint8_t*)message.data) & 2; - controllers.front.feedback.right.hallC = *((uint8_t*)message.data) & 4; - break; + if (millis() - controllers.front.lastCanFeedback > 100) + controllers.front.feedbackValid = false; + + if (millis() - controllers.back.lastCanFeedback > 100) + controllers.back.feedbackValid = false; + + if (result != ESP_ERR_TIMEOUT) + Serial.printf("CAN err can_receive() failed with %s\r\n", esp_err_to_name(result)); + + return false; } - case MotorControllerFrontLeftVoltage: - m_lastCanFeedback = millis(); + + if (parseCanMessage(message)) + { + if (millis() - controllers.back.lastCanFeedback > 100) + controllers.back.feedbackValid = false; + + controllers.front.lastCanFeedback = millis(); controllers.front.feedbackValid = true; - controllers.front.feedback.batVoltage = *((int16_t*)message.data); + return true; + } + else + { + if (millis() - controllers.front.lastCanFeedback > 100) + controllers.front.feedbackValid = false; + } + + if (parseCanMessage(message)) + { + controllers.back.lastCanFeedback = millis(); + controllers.back.feedbackValid = true; + return true; + } + else + { + if (millis() - controllers.back.lastCanFeedback > 100) + controllers.back.feedbackValid = false; + } + + Serial.printf("WARNING Unknown CAN info received .identifier = %u\r\n", message.identifier); + + return true; +} + +void sendCanCommands() +{ + constexpr auto send = [](uint32_t addr, auto value){ + can_message_t message; + message.identifier = addr; + message.flags = CAN_MSG_FLAG_SS; + message.data_length_code = sizeof(value); + std::fill(std::begin(message.data), std::end(message.data), 0); + std::memcpy(message.data, &value, sizeof(value)); + + const auto result = can_transmit(&message, pdMS_TO_TICKS(200)); + if (result != ESP_OK && result != ESP_ERR_TIMEOUT) + Serial.printf("ERROR: can_transmit() failed with %s\r\n", esp_err_to_name(result)); + return result; + }; + + using namespace bobbycar::can; + + send(MotorController::Command::InpTgt, controllers.front.command.left.pwm); + send(MotorController::Command::InpTgt, controllers.front.command.right.pwm); + send(MotorController::Command::InpTgt, controllers.back.command.left.pwm); + send(MotorController::Command::InpTgt, controllers.back.command.right.pwm); + + static int i{}; + switch (i++) + { + case 0: + send(MotorController::Command::Enable, controllers.front.command.left.enable); + send(MotorController::Command::Enable, controllers.front.command.right.enable); + send(MotorController::Command::Enable, controllers.back.command.left.enable); + send(MotorController::Command::Enable, controllers.back.command.right.enable); break; - case MotorControllerFrontLeftTemp: - m_lastCanFeedback = millis(); - controllers.front.feedbackValid = true; - controllers.front.feedback.boardTemp = *((int16_t*)message.data); + case 1: + send(MotorController::Command::CtrlTyp, controllers.front.command.left.ctrlTyp); + send(MotorController::Command::CtrlTyp, controllers.front.command.right.ctrlTyp); + send(MotorController::Command::CtrlTyp, controllers.back.command.left.ctrlTyp); + send(MotorController::Command::CtrlTyp, controllers.back.command.right.ctrlTyp); + break; + case 2: + send(MotorController::Command::CtrlMod, controllers.front.command.left.ctrlMod); + send(MotorController::Command::CtrlMod, controllers.front.command.right.ctrlMod); + send(MotorController::Command::CtrlMod, controllers.back.command.left.ctrlMod); + send(MotorController::Command::CtrlMod, controllers.back.command.right.ctrlMod); + break; + case 3: + send(MotorController::Command::IMotMax, controllers.front.command.left.iMotMax); + send(MotorController::Command::IMotMax, controllers.front.command.right.iMotMax); + send(MotorController::Command::IMotMax, controllers.back.command.left.iMotMax); + send(MotorController::Command::IMotMax, controllers.back.command.right.iMotMax); + break; + case 4: + send(MotorController::Command::IDcMax, controllers.front.command.left.iDcMax); + send(MotorController::Command::IDcMax, controllers.front.command.right.iDcMax); + send(MotorController::Command::IDcMax, controllers.back.command.left.iDcMax); + send(MotorController::Command::IDcMax, controllers.back.command.right.iDcMax); + break; + case 5: + send(MotorController::Command::NMotMax, controllers.front.command.left.nMotMax); + send(MotorController::Command::NMotMax, controllers.front.command.right.nMotMax); + send(MotorController::Command::NMotMax, controllers.back.command.left.nMotMax); + send(MotorController::Command::NMotMax, controllers.back.command.right.nMotMax); + break; + case 6: + send(MotorController::Command::FieldWeakMax, controllers.front.command.left.fieldWeakMax); + send(MotorController::Command::FieldWeakMax, controllers.front.command.right.fieldWeakMax); + send(MotorController::Command::FieldWeakMax, controllers.back.command.left.fieldWeakMax); + send(MotorController::Command::FieldWeakMax, controllers.back.command.right.fieldWeakMax); + break; + case 7: + send(MotorController::Command::PhaseAdvMax, controllers.front.command.left.phaseAdvMax); + send(MotorController::Command::PhaseAdvMax, controllers.front.command.right.phaseAdvMax); + send(MotorController::Command::PhaseAdvMax, controllers.back.command.left.phaseAdvMax); + send(MotorController::Command::PhaseAdvMax, controllers.back.command.right.phaseAdvMax); + break; + case 8: + send(MotorController::Command::BuzzerFreq, controllers.front.command.buzzer.freq); + send(MotorController::Command::BuzzerFreq, controllers.front.command.buzzer.freq); + send(MotorController::Command::BuzzerFreq, controllers.back.command.buzzer.freq); + send(MotorController::Command::BuzzerFreq, controllers.back.command.buzzer.freq); + break; + case 9: + send(MotorController::Command::BuzzerPattern, controllers.front.command.buzzer.pattern); + send(MotorController::Command::BuzzerPattern, controllers.front.command.buzzer.pattern); + send(MotorController::Command::BuzzerPattern, controllers.back.command.buzzer.pattern); + send(MotorController::Command::BuzzerPattern, controllers.back.command.buzzer.pattern); + break; + case 10: + send(MotorController::Command::Led, controllers.front.command.led); + send(MotorController::Command::Led, controllers.front.command.led); + send(MotorController::Command::Led, controllers.back.command.led); + send(MotorController::Command::Led, controllers.back.command.led); + break; + case 11: + send(MotorController::Command::Poweroff, controllers.front.command.poweroff); + send(MotorController::Command::Poweroff, controllers.front.command.poweroff); + send(MotorController::Command::Poweroff, controllers.back.command.poweroff); + send(MotorController::Command::Poweroff, controllers.back.command.poweroff); + i=0; break; - default: - Serial.printf("WARNING Unknown CAN info received .identifier = %u\r\n", message.identifier); } } } diff --git a/src/controller.h b/src/controller.h index 8eb5486..d045c7c 100644 --- a/src/controller.h +++ b/src/controller.h @@ -5,6 +5,8 @@ #include "bobbycar-protocol/bobbycar-common.h" #include "bobbycar-protocol/bobbycar-serial.h" +#include "types.h" + #ifndef FEATURE_CAN #include "feedbackparser.h" #endif @@ -36,6 +38,9 @@ struct Controller { Command command{}; +#ifdef FEATURE_CAN + millis_t lastCanFeedback{}; +#endif bool feedbackValid{}; Feedback feedback{}; diff --git a/src/main.cpp b/src/main.cpp index 9c754e7..a30f12b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -429,7 +429,9 @@ void loop() } #ifdef FEATURE_CAN - parseCanInput(); + for (int i = 0; i < 4; i++) + if (!parseCanInput()) + break; #else for (Controller &controller : controllers) controller.parser.update(); diff --git a/src/utils.h b/src/utils.h index a346ab4..4ced218 100644 --- a/src/utils.h +++ b/src/utils.h @@ -2,7 +2,6 @@ #include #include -#include #include @@ -14,6 +13,9 @@ #include "display.h" #include "globals.h" +#ifdef FEATURE_CAN +#include "can.h" +#endif // macros are a shit piece of software #define STRING2(s) #s @@ -259,108 +261,8 @@ void sendCommands() controller.command.checksum = calculateChecksum(controller.command); controller.serial.get().write((uint8_t *) &controller.command, sizeof(controller.command)); } -#endif - -#ifdef FEATURE_CAN - constexpr auto send = [](uint32_t addr, auto value){ - can_message_t message; - message.identifier = addr; - if (addr == MotorControllerFrontLeftInpTgt || addr == MotorControllerFrontRightInpTgt) - message.flags = CAN_MSG_FLAG_SS; - else - message.flags = CAN_MSG_FLAG_NONE; - message.data_length_code = sizeof(value); - std::fill(std::begin(message.data), std::end(message.data), 0); - std::memcpy(message.data, &value, sizeof(value)); - - const auto result = can_transmit(&message, pdMS_TO_TICKS(200)); - if (result != ESP_OK && result != ESP_ERR_TIMEOUT) - Serial.printf("ERROR: can_transmit() failed with %s\r\n", esp_err_to_name(result)); - return result; - }; - - send(MotorControllerFrontLeftInpTgt, controllers.front.command.left.pwm); - send(MotorControllerFrontRightInpTgt, controllers.front.command.right.pwm); -// send(MotorControllerBackLeftInpTgt, controllers.back.command.left.pwm); -// send(MotorControllerBackRightInpTgt, controllers.back.command.right.pwm); - - static int i = 0; - switch (i++) - { - case 0: - send(MotorControllerFrontLeftEnable, controllers.front.command.left.enable); - send(MotorControllerFrontRightEnable, controllers.front.command.right.enable); -// send(MotorControllerBackLeftEnable, controllers.back.command.left.enable); -// send(MotorControllerBackRightEnable, controllers.back.command.right.enable); - break; - case 1: - send(MotorControllerFrontLeftCtrlTyp, controllers.front.command.left.ctrlTyp); - send(MotorControllerFrontRightCtrlTyp, controllers.front.command.right.ctrlTyp); -// send(MotorControllerBackLeftCtrlTyp, controllers.back.command.left.ctrlTyp); -// send(MotorControllerBackRightCtrlTyp, controllers.back.command.right.ctrlTyp); - break; - case 2: - send(MotorControllerFrontLeftCtrlMod, controllers.front.command.left.ctrlMod); - send(MotorControllerFrontRightCtrlMod, controllers.front.command.right.ctrlMod); -// send(MotorControllerBackLeftCtrlMod, controllers.back.command.left.ctrlMod); -// send(MotorControllerBackRightCtrlMod, controllers.back.command.right.ctrlMod); - break; - case 3: - send(MotorControllerFrontLeftIMotMax, controllers.front.command.left.iMotMax); - send(MotorControllerFrontRightIMotMax, controllers.front.command.right.iMotMax); -// send(MotorControllerBackLeftIMotMax, controllers.back.command.left.iMotMax); -// send(MotorControllerBackRightIMotMax, controllers.back.command.right.iMotMax); - break; - case 4: - send(MotorControllerFrontLeftIDcMax, controllers.front.command.left.iDcMax); - send(MotorControllerFrontRightIDcMax, controllers.front.command.right.iDcMax); -// send(MotorControllerBackLeftIDcMax, controllers.back.command.left.iDcMax); -// send(MotorControllerBackRightIDcMax, controllers.back.command.right.iDcMax); - break; - case 5: - send(MotorControllerFrontLeftNMotMax, controllers.front.command.left.nMotMax); - send(MotorControllerFrontRightNMotMax, controllers.front.command.right.nMotMax); -// send(MotorControllerBackLeftNMotMax, controllers.back.command.left.nMotMax); -// send(MotorControllerBackRightNMotMax, controllers.back.command.right.nMotMax); - break; - case 6: - send(MotorControllerFrontLeftFieldWeakMax, controllers.front.command.left.fieldWeakMax); - send(MotorControllerFrontRightFieldWeakMax, controllers.front.command.right.fieldWeakMax); -// send(MotorControllerBackLeftFieldWeakMax, controllers.back.command.left.fieldWeakMax); -// send(MotorControllerBackRightFieldWeakMax, controllers.back.command.right.fieldWeakMax); - break; - case 7: - send(MotorControllerFrontLeftPhaseAdvMax, controllers.front.command.left.phaseAdvMax); - send(MotorControllerFrontRightPhaseAdvMax, controllers.front.command.right.phaseAdvMax); -// send(MotorControllerBackLeftPhaseAdvMax, controllers.back.command.left.phaseAdvMax); -// send(MotorControllerBackRightPhaseAdvMax, controllers.back.command.right.phaseAdvMax); - break; - case 8: - send(MotorControllerFrontLeftBuzzerFreq, controllers.front.command.buzzer.freq); - send(MotorControllerFrontRightBuzzerFreq, controllers.front.command.buzzer.freq); -// send(MotorControllerBackLeftBuzzerFreq, controllers.back.command.buzzer.freq); -// send(MotorControllerBackRightBuzzerFreq, controllers.back.command.buzzer.freq); - break; - case 9: - send(MotorControllerFrontLeftBuzzerPattern, controllers.front.command.buzzer.pattern); - send(MotorControllerFrontRightBuzzerPattern, controllers.front.command.buzzer.pattern); -// send(MotorControllerBackLeftBuzzerPattern, controllers.back.command.buzzer.pattern); -// send(MotorControllerBackRightBuzzerPattern, controllers.back.command.buzzer.pattern); - break; - case 10: - send(MotorControllerFrontLeftLed, controllers.front.command.led); - send(MotorControllerFrontRightLed, controllers.front.command.led); -// send(MotorControllerBackLeftLed, controllers.back.command.led); -// send(MotorControllerBackRightLed, controllers.back.command.led); - break; - case 11: - send(MotorControllerFrontLeftPoweroff, controllers.front.command.poweroff); - send(MotorControllerFrontRightPoweroff, controllers.front.command.poweroff); -// send(MotorControllerBackLeftPoweroff, controllers.back.command.poweroff); -// send(MotorControllerBackRightPoweroff, controllers.back.command.poweroff); - i=0; - break; - } +#else + sendCanCommands(); #endif }