diff --git a/examples/bridge_firmware_updater/bridge_firmware_updater b/examples/bridge_firmware_updater/bridge_firmware_updater new file mode 100644 index 0000000..d2e0ff8 --- /dev/null +++ b/examples/bridge_firmware_updater/bridge_firmware_updater @@ -0,0 +1,85 @@ +/* + This file is part of the Arduino_Alvik library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +*/ + + +/* + You can use this sketch to make your Arduino Nano ESP32 an USB-to-serial adapter. + This allows to flash firmware into the Arduino Alvik Carrier via Arduino Nano ESP32. + + Please refer to Arduino_AlvikCarrier library available at https://github.com/arduino-libraries/Arduino_AlvikCarrier +*/ + + + + +#include "Arduino_Alvik.h" + +unsigned long baud = 115200; + +int rts = -1; +int dtr = -1; + + +static void onLineChange(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { + if (event_base == ARDUINO_USB_CDC_EVENTS) { + arduino_usb_cdc_event_data_t * data = (arduino_usb_cdc_event_data_t*)event_data; + switch (event_id) { + case ARDUINO_USB_CDC_LINE_CODING_EVENT: + auto baud = data->line_coding.bit_rate; + Serial0.updateBaudRate(baud); + while (Serial0.available()) { + Serial0.read(); + } + break; + } + } +} + +void setup() { + Serial.onEvent(onLineChange); + Serial.enableReboot(false); + Serial.begin(baud); + Serial.setRxBufferSize(0); + Serial.setRxBufferSize(2048); + Serial0.setRxBufferSize(8192); + Serial0.setTxBufferSize(8192); + Serial0.begin(baud, SERIAL_8E1); + Serial0.flush(); + pinMode(BOOT_STM32, OUTPUT); + pinMode(RESET_STM32, OUTPUT); + digitalWrite(BOOT_STM32,HIGH); + delay(1000); + digitalWrite(RESET_STM32,LOW); + delay(1000); + digitalWrite(RESET_STM32,HIGH); + + + +} + +void loop() { + int len = 0; + uint8_t auc_buffer[488]; + while (Serial.available() && len < sizeof(auc_buffer)) { + auc_buffer[len++] = Serial.read(); + } + if (len) { + Serial0.write(auc_buffer, len); + } + + len = 0; + while (Serial0.available() && len < sizeof(auc_buffer)) { + auc_buffer[len++] = Serial0.read(); + } + if (len) { + Serial.write(auc_buffer, len); + } +} \ No newline at end of file diff --git a/examples/color_calibration/color_calibration.ino b/examples/color_calibration/color_calibration.ino index dc0290c..07104c4 100644 --- a/examples/color_calibration/color_calibration.ino +++ b/examples/color_calibration/color_calibration.ino @@ -36,7 +36,7 @@ void setup() { } void loop() { - int16_t color[3]; + int color[3]; float rgb[3]; float hsv[3]; alvik.get_color_raw(color[0], color[1], color[2]); diff --git a/examples/drive/drive.ino b/examples/drive/drive.ino new file mode 100644 index 0000000..c63eb21 --- /dev/null +++ b/examples/drive/drive.ino @@ -0,0 +1,25 @@ +/* + This file is part of the Arduino_Alvik library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +*/ + +#include "Arduino_Alvik.h" + +Arduino_Alvik alvik; + +void setup() { + alvik.begin(); +} + +void loop() { + alvik.drive(10, 45); + delay(10000); + alvik.drive(10, -45); + delay(10000); +} \ No newline at end of file diff --git a/examples/line_follower/line_follower.ino b/examples/line_follower/line_follower.ino new file mode 100644 index 0000000..6069789 --- /dev/null +++ b/examples/line_follower/line_follower.ino @@ -0,0 +1,83 @@ +/* + This file is part of the Arduino_Alvik library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +*/ + +#include "Arduino_Alvik.h" + +Arduino_Alvik alvik; + +int line_sensors[3]; +float error = 0; +float control = 0; +float kp = 50.0; + + + +void setup() { + Serial.begin(115200); + while((!Serial)&&(millis()>3000)); + alvik.begin(); + alvik.left_led.set_color(0,0,1); + alvik.right_led.set_color(0,0,1); + + while(!alvik.get_touch_ok()){ + delay(50); + } +} + +void loop() { + while (!alvik.get_touch_cancel()){ + + alvik.get_line_sensors(line_sensors[0], line_sensors[1], line_sensors[2]); + Serial.print(line_sensors[0]); + Serial.print("\t"); + Serial.print(line_sensors[1]); + Serial.print("\t"); + Serial.print(line_sensors[2]); + Serial.print("\n"); + error = calculate_center(line_sensors[0], line_sensors[1], line_sensors[2]); + control = error * kp; + if (control > 0.2){ + alvik.left_led.set_color(1,0,0); + alvik.right_led.set_color(0,0,0); + } + else{ + if (control < -0.2){ + alvik.left_led.set_color(0,0,0); + alvik.right_led.set_color(1,0,0); + } + else{ + alvik.left_led.set_color(0,1,0); + alvik.right_led.set_color(0,1,0); + } + } + + alvik.set_wheels_speed(30-control, 30+control); + delay(100); + } + + while (!alvik.get_touch_ok()){ + alvik.left_led.set_color(0,0,1); + alvik.right_led.set_color(0,0,1); + alvik.brake(); + delay(100); + } +} + +float calculate_center(const int left, const int center, const int right){ + float centroid = 0.0; + float sum_weight = left + center + right; + float sum_values = left + center * 2 + right * 3; + if (sum_weight!=0.0){ // divide by zero protection + centroid=sum_values/sum_weight; + centroid=-centroid+2.0; // so it is right on robot axis Y + } + return centroid; +} diff --git a/examples/remote_control/remote_control.ino b/examples/remote_control/remote_control.ino new file mode 100644 index 0000000..0b978ef --- /dev/null +++ b/examples/remote_control/remote_control.ino @@ -0,0 +1,122 @@ +/* + This file is part of the Arduino_Alvik library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +*/ + +// This example shows how to interface 2 Alvik robots via ESPnow. +// At startup, you can select if an Alvik is a trasmitter by pressing the "check button" or a receiver by pressing "cancel button". Use arrows to move the robot. + +#include "Arduino_Alvik.h" +#include +#include + +Arduino_Alvik alvik; + +uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; +uint8_t myData; +esp_now_peer_info_t peerInfo; + + +int alvik_mode = -1; // 0 is receiver, 1 is sender + +bool led_blink = false; + + +void setup() { + Serial.begin(115200); + while((!Serial)&&(millis()>3000)); + + alvik.begin(); + + WiFi.mode(WIFI_STA); + if (esp_now_init() != ESP_OK) { + Serial.println("Error initializing ESP-NOW"); + return; + } + + while (alvik_mode == -1){ + if (alvik.get_touch_cancel()){ + alvik_mode = 0; + } + if (alvik.get_touch_ok()){ + alvik_mode = 1; + } + } + if (alvik_mode == 0){ + esp_now_register_recv_cb(OnDataRecv); + } + else{ + memcpy(peerInfo.peer_addr, broadcastAddress, 6); + peerInfo.channel = 0; + peerInfo.encrypt = false; + + if (esp_now_add_peer(&peerInfo) != ESP_OK){ + Serial.println("Failed to add peer"); + return; + } + } +} + +void loop() { + if (alvik_mode==0){ + alvik.left_led.set_color(led_blink, !led_blink, 0); + alvik.right_led.set_color(!led_blink, led_blink, 0); + delay(500); + } + else{ + if (alvik.get_touch_any()){ + if (alvik.get_touch_up()){ + myData = 'F'; + esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData)); + } + if (alvik.get_touch_down()){ + myData = 'B'; + esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData)); + } + if (alvik.get_touch_left()){ + myData = 'L'; + esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData)); + } + if (alvik.get_touch_right()){ + myData = 'R'; + esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData)); + } + if (alvik.get_touch_center()){ + myData = 'S'; + esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData)); + } + } + alvik.left_led.set_color(0, 0, led_blink); + alvik.right_led.set_color(0, 0, led_blink); + delay(100); + } + led_blink = !led_blink; +} + +void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len){ + Serial.print(incomingData[0]); + switch (incomingData[0]){ + case 'F': + alvik.drive(7, 0); + break; + case 'B': + alvik.drive(-7, 0); + break; + case 'L': + alvik.drive(0, 45); + break; + case 'R': + alvik.drive(0, -45); + break; + case 'S': + alvik.brake(); + break; + } + Serial.println(); +} \ No newline at end of file diff --git a/library.properties b/library.properties index 420c3dc..6bfa9dc 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Arduino_Alvik -version=0.2.0 +version=0.3.0 author=Arduino, Giovanni di Dio Bruno, Lucio Rossi maintainer=Arduino sentence=Library to code Arduino Alvik robot diff --git a/src/Arduino_Alvik.cpp b/src/Arduino_Alvik.cpp index 9131cd0..5c2d6e3 100644 --- a/src/Arduino_Alvik.cpp +++ b/src/Arduino_Alvik.cpp @@ -50,10 +50,12 @@ void Arduino_Alvik::wait_for_ack(){ } } -int Arduino_Alvik::begin(){ +int Arduino_Alvik::begin(const bool verbose, const uint8_t core){ pinMode(LED_RED, OUTPUT); pinMode(LED_GREEN, OUTPUT); + verbose_output = verbose; + last_ack = 0; version[0] = 0; @@ -121,6 +123,9 @@ int Arduino_Alvik::begin(){ robot_pose[1] = 0.0; robot_pose[2] = 0.0; + battery = 0.0; + battery_soc = 0.0; + @@ -139,7 +144,7 @@ int Arduino_Alvik::begin(){ } //begin_update_thread(); - xTaskCreatePinnedToCore(this->update_thread, "update", 10000, this, 1, &update_task, 0); + xTaskCreatePinnedToCore(this->update_thread, "update", 10000, this, 1, &update_task, core); delay(100); reset_hw(); @@ -166,24 +171,28 @@ bool Arduino_Alvik::is_on(){ void Arduino_Alvik::idle(){ digitalWrite(NANO_CHK, HIGH); delay(500); + bool led_value=false; while(!is_on()){ //read battery value - /* - pinMode(A4, OUTPUT); - pinMode(A5, OUTPUT); - digitalWrite(A4, HIGH); - digitalWrite(A5, HIGH); - delay(100); - digitalWrite(A4, LOW); - digitalWrite(A5, LOW); - delay(100); - Wire.begin(); - */ - digitalWrite(LED_GREEN, HIGH); - delay(1000); - digitalWrite(LED_GREEN, LOW); + battery_measure(); + if (verbose_output){ + Serial.print(round(battery_soc)); + Serial.println("%"); + } + if (battery_soc>CHARGE_THRESHOLD){ + digitalWrite(LED_GREEN, LOW); + digitalWrite(LED_RED, HIGH); + } + else{ + digitalWrite(LED_GREEN, HIGH); + led_value = !led_value; + digitalWrite(LED_RED, led_value); + } delay(1000); } + digitalWrite(LED_GREEN, HIGH); + digitalWrite(LED_RED, HIGH); + digitalWrite(NANO_CHK, LOW); } @@ -315,6 +324,11 @@ int Arduino_Alvik::parse_message(){ xSemaphoreGive(version_semaphore); break; + // get battery parcentage: state of charge + case 'p': + packeter->unpacketC1F(code, battery); + break; + // nothing is parsed, the command is newer to this library default: return -1; @@ -433,7 +447,34 @@ void Arduino_Alvik::brake(){ // sensors // //-----------------------------------------------------------------------------------------------// -void Arduino_Alvik::get_line_sensors(int16_t & left, int16_t & center, int16_t & right){ +float Arduino_Alvik::battery_measure(){ //it is private + pinMode(A4,OUTPUT); + pinMode(A5,OUTPUT); + digitalWrite(A4,HIGH); + digitalWrite(A5,HIGH); + delay(100); + digitalWrite(A4,LOW); + digitalWrite(A5,LOW); + Wire.begin(); + Wire.beginTransmission(0x36); + Wire.write(0x06); + if (Wire.endTransmission(false)!=0){ + Serial.println("Error on opening BMS"); + while(1); + } + else{ + Wire.requestFrom(0x36, 2); + battery_v[0] = Wire.read(); + battery_v[1] = Wire.read(); + battery_val = (battery_v[1] << 8) + battery_v[0]; + battery_soc = battery_val * 0.00390625; + } + Wire.end(); + return battery_soc; +} + + +void Arduino_Alvik::get_line_sensors(int & left, int & center, int & right){ while (!xSemaphoreTake(line_semaphore, 5)){} left = line_sensors[0]; center = line_sensors[1]; @@ -442,7 +483,7 @@ void Arduino_Alvik::get_line_sensors(int16_t & left, int16_t & center, int16_t & } -void Arduino_Alvik::get_color_raw(int16_t & red, int16_t & green, int16_t & blue){ +void Arduino_Alvik::get_color_raw(int & red, int & green, int & blue){ while (!xSemaphoreTake(color_semaphore, 5)){} red = color_sensor[0]; green = color_sensor[1]; @@ -549,7 +590,7 @@ void Arduino_Alvik::get_color(float & value0, float & value1, float & value2, co } } -uint8_t Arduino_Alvik::get_color_label(const float h, const float s, const float v){ +uint8_t Arduino_Alvik::get_color_id(const float h, const float s, const float v){ if (s < MINIMUM_SATURATION){ if (v < 0.05){ return BLACK; @@ -618,10 +659,18 @@ uint8_t Arduino_Alvik::get_color_label(const float h, const float s, const float } } -uint8_t Arduino_Alvik::get_color_label(){ +uint8_t Arduino_Alvik::get_color_id(){ float h,s,v; get_color(h, s, v, HSV); - return get_color_label(h, s, v); + return get_color_id(h, s, v); +} + +String Arduino_Alvik::get_color_label(const float h, const float s, const float v){ + return COLOR_LABELS[get_color_id(h, s, v)]; +} + +String Arduino_Alvik::get_color_label(){ + return COLOR_LABELS[get_color_id()]; } void Arduino_Alvik::color_calibration(const uint8_t background){ @@ -631,7 +680,7 @@ void Arduino_Alvik::color_calibration(const uint8_t background){ int red_avg = 0; int green_avg = 0; int blue_avg = 0; - int16_t red, green, blue; + int red, green, blue; for (int i=0; i #include "default_colors.h" +#include "Wire.h" class Arduino_Alvik{ @@ -27,6 +28,7 @@ class Arduino_Alvik{ HardwareSerial * uart; + bool verbose_output; uint8_t b; uint8_t code; @@ -77,6 +79,11 @@ class Arduino_Alvik{ SemaphoreHandle_t robot_pos_semaphore; float robot_pose[3]; + float battery; + float battery_soc; + uint16_t battery_val = 0; + uint8_t battery_v[2]; + void reset_hw(); // reset the robot @@ -91,9 +98,11 @@ class Arduino_Alvik{ void set_leds(); // service function to set leds by a byte void wait_for_target(); // service function that wait for ack - float limit(float value, const float min, const float max); - float normalize(float value, const float min, const float max); - void load_color_calibration(); + float limit(float value, const float min, const float max); // limit a value + float normalize(float value, const float min, const float max); // normalize a value + void load_color_calibration(); // service function to get data from eeprom + + float battery_measure(); // service function to get data from bms @@ -154,7 +163,7 @@ class Arduino_Alvik{ Arduino_Alvik(); - int begin(); + int begin(const bool verbose = true, const uint8_t core = RUN_ON_CORE_0); void stop(); bool is_on(); void idle(); @@ -182,14 +191,16 @@ class Arduino_Alvik{ void brake(); - void get_line_sensors(int16_t & left, int16_t & center, int16_t & right); + void get_line_sensors(int & left, int & center, int & right); - void get_color_raw(int16_t & red, int16_t & green, int16_t & blue); + void get_color_raw(int & red, int & green, int & blue); void rgb2norm(const int16_t r, const int16_t g, const int16_t b, float & r_norm, float & g_norm, float & b_norm); void norm2hsv(const float r, const float g, const float b, float & h, float & s, float & v); void get_color(float & value0, float & value1, float & value2, const uint8_t format = RGB); - uint8_t get_color_label(const float h, const float s, const float v); - uint8_t get_color_label(); + uint8_t get_color_id(const float h, const float s, const float v); + uint8_t get_color_id(); + String get_color_label(const float h, const float s, const float v); + String get_color_label(); void color_calibration(const uint8_t background = WHITE); void get_orientation(float & roll, float & pitch, float & yaw); @@ -220,6 +231,8 @@ class Arduino_Alvik{ void set_behaviour(const uint8_t behaviour); void get_version(uint8_t & upper, uint8_t & middle, uint8_t & lower); + + int get_battery_charge(); }; diff --git a/src/definitions.h b/src/definitions.h index df86ef4..60e7d5a 100644 --- a/src/definitions.h +++ b/src/definitions.h @@ -15,6 +15,11 @@ #include "Arduino.h" +#define RUN_ON_CORE_0 0 +#define RUN_ON_CORE_1 1 +#define NO_VERBOSE 0 +#define VERBOSE 1 + #define CHECK_STM32 A6 #define BOOT_STM32 D2 #define RESET_STM32 D3 @@ -22,6 +27,8 @@ #define UART 0 #define UART_BAUD_RATE 460800 +#define CHARGE_THRESHOLD 97 + const float WHEEL_DIAMETER_MM = 34.0; const float WHEEL_TRACK_MM = 89.0; const float MOTOR_MAX_RPM = 70.0;