-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
475 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
bin/ | ||
*.log |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
[submodule "rust-arduino-serial"] | ||
path = rust-arduino-serial | ||
url = https://github.com/araffin/rust-arduino-serial | ||
[submodule "cpp-arduino-serial"] | ||
path = cpp-arduino-serial | ||
url = https://github.com/araffin/cpp-arduino-serial.git | ||
[submodule "python-arduino-serial"] | ||
path = python-arduino-serial | ||
url = https://github.com/araffin/python-arduino-serial.git |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
# Robust Arduino Serial Protocol | ||
|
||
**Robust Arduino Serial** is a simple and robust serial communication protocol. It was designed to make two Arduinos communicate, but can also be useful when you want a computer (e.g. a Raspberry Pi) to communicate with an Arduino. | ||
|
||
**Please read the [Medium Article](https://medium.com/@araffin/simple-and-robust-computer-arduino-serial-communication-f91b95596788) to have an overview of this protocol.** | ||
|
||
Implementations are available for: | ||
|
||
- Arduino (`arduino-serial/` folder) | ||
- [Python](https://github.com/araffin/python-arduino-serial) | ||
- [C++](https://github.com/araffin/cpp-arduino-serial) | ||
- [Rust](https://github.com/araffin/rust-arduino-serial) | ||
|
||
|
||
**Examples** are provided in each repository. | ||
|
||
### Arduino Implementation | ||
|
||
Recommended: Arduino-Makefile | ||
``` | ||
sudo apt-get install arduino-mk | ||
``` | ||
|
||
Compile and upload the code to the Arduino (please check the board name in the Makefile): | ||
``` | ||
cd arduino-board/ | ||
make | ||
make upload | ||
``` | ||
|
||
### Python Implementation | ||
|
||
[](https://travis-ci.org/araffin/python-arduino-serial) | ||
|
||
Python repository: [https://github.com/araffin/python-arduino-serial]((https://github.com/araffin/python-arduino-serial) | ||
|
||
### C++ Implementation | ||
|
||
[](https://travis-ci.org/araffin/cpp-arduino-serial) | ||
|
||
|
||
C++ repository: [https://github.com/araffin/cpp-arduino-serial]((https://github.com/araffin/cpp-arduino-serial) | ||
|
||
|
||
### Rust Implementation | ||
|
||
[](https://travis-ci.org/araffin/rust-arduino-serial) [](https://ci.appveyor.com/project/araffin/rust-arduino-serial/branch/master) | ||
|
||
Rust repository: [https://github.com/araffin/rust-arduino-serial]((https://github.com/araffin/rust-arduino-serial) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
### DISCLAIMER | ||
### This is an example Makefile and it MUST be configured to suit your needs. | ||
### For detailled explanations about all the avalaible options, | ||
### please refer to https://github.com/sudar/Arduino-Makefile/blob/master/arduino-mk-vars.md | ||
### Original project where this Makefile comes from: https://github.com/WeAreLeka/Bare-Arduino-Project | ||
|
||
### PROJECT_DIR | ||
### This is the path to where you have created/cloned your project | ||
PROJECT_DIR = $(shell pwd) | ||
|
||
### ARDMK_DIR | ||
### Path to the Arduino-Makefile directory. | ||
ARDMK_DIR = /usr/share/arduino | ||
|
||
### ARDUINO_DIR | ||
### Path to the Arduino application and ressources directory. | ||
|
||
### or on Linux: (remove the one you don't want) | ||
ARDUINO_DIR = /usr/share/arduino | ||
|
||
### USER_LIB_PATH | ||
### Path to where the your project's libraries are stored. | ||
USER_LIB_PATH := $(PROJECT_DIR)/lib | ||
|
||
### BOARD_TAG | ||
### It must be set to the board you are currently using. (i.e uno, mega2560, etc.) | ||
BOARD_TAG = uno | ||
|
||
### MONITOR_BAUDRATE | ||
### It must be set to Serial baudrate value you are using. | ||
MONITOR_BAUDRATE = 115200 | ||
|
||
### AVR_TOOLS_DIR | ||
### Path to the AVR tools directory such as avr-gcc, avr-g++, etc. | ||
### On OS X with `homebrew`: | ||
AVR_TOOLS_DIR = /usr/local | ||
### or on Linux: (remove the one you don't want) | ||
AVR_TOOLS_DIR = /usr | ||
|
||
### AVRDDUDE | ||
### Path to avrdude directory. | ||
### On OS X with `homebrew`: | ||
AVRDDUDE = /usr/local/bin/avrdude | ||
### or on Linux: (remove the one you don't want) | ||
AVRDDUDE = /usr/bin/avrdude | ||
|
||
### CFLAGS_STD | ||
### Set the C standard to be used during compilation. Documentation (https://github.com/WeAreLeka/Arduino-Makefile/blob/std-flags/arduino-mk-vars.md#cflags_std) | ||
CFLAGS_STD = -std=gnu11 | ||
|
||
### CXXFLAGS_STD | ||
### Set the C++ standard to be used during compilation. Documentation (https://github.com/WeAreLeka/Arduino-Makefile/blob/std-flags/arduino-mk-vars.md#cxxflags_std) | ||
CXXFLAGS_STD = -std=gnu++11 | ||
|
||
### CXXFLAGS | ||
### Flags you might want to set for debugging purpose. Comment to stop. | ||
CXXFLAGS += -pedantic -Wall -Wextra | ||
|
||
### MONITOR_PORT | ||
### The port your board is connected to. Using an '*' tries all the ports and finds the right one. | ||
MONITOR_PORT = /dev/ttyACM* | ||
|
||
### CURRENT_DIR | ||
### Do not touch - used for binaries path | ||
CURRENT_DIR = $(shell basename $(CURDIR)) | ||
|
||
### OBJDIR | ||
### This is were you put the binaries you just compile using 'make' | ||
OBJDIR = $(PROJECT_DIR)/bin/$(BOARD_TAG)/$(CURRENT_DIR) | ||
|
||
### path to Arduino.mk, inside the ARDMK_DIR, don't touch. | ||
include $(ARDMK_DIR)/Arduino.mk |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#ifndef ORDER_H | ||
#define ORDER_H | ||
|
||
// Define the orders that can be sent and received | ||
enum Order { | ||
HELLO = 0, | ||
SERVO = 1, | ||
MOTOR = 2, | ||
ALREADY_CONNECTED = 3, | ||
ERROR = 4, | ||
RECEIVED = 5, | ||
STOP = 6, | ||
}; | ||
|
||
typedef enum Order Order; | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#ifndef PARAMETERS_H | ||
#define PARAMETERS_H | ||
|
||
#define SERIAL_BAUD 115200 // Baudrate | ||
#define MOTOR_PIN 3 | ||
#define DIRECTION_PIN 4 | ||
#define SERVOMOTOR_PIN 6 | ||
#define INITIAL_THETA 110 // Initial angle of the servomotor | ||
// Min and max values for motors | ||
#define THETA_MIN 60 | ||
#define THETA_MAX 150 | ||
#define SPEED_MAX 100 | ||
|
||
// If DEBUG is set to true, the arduino will send back all the received messages | ||
#define DEBUG false | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,215 @@ | ||
#include <Arduino.h> | ||
#include <Servo.h> | ||
|
||
#include "order.h" | ||
#include "slave.h" | ||
#include "parameters.h" | ||
|
||
bool is_connected = false; ///< True if the connection with the master is available | ||
int8_t motor_speed = 0; | ||
int16_t servo_angle = INITIAL_THETA; | ||
Servo servomotor; | ||
|
||
void setup() | ||
{ | ||
// Init Serial | ||
Serial.begin(SERIAL_BAUD); | ||
|
||
// Init Motor | ||
pinMode(MOTOR_PIN, OUTPUT); | ||
pinMode(DIRECTION_PIN, OUTPUT); | ||
// Stop the car | ||
stop(); | ||
|
||
// Init Servo | ||
servomotor.attach(SERVOMOTOR_PIN); | ||
// Order between 0 and 180 | ||
servomotor.write(INITIAL_THETA); | ||
|
||
// Wait until the arduino is connected to master | ||
while(!is_connected) | ||
{ | ||
write_order(HELLO); | ||
wait_for_bytes(1, 1000); | ||
get_messages_from_serial(); | ||
} | ||
|
||
} | ||
|
||
void loop() | ||
{ | ||
get_messages_from_serial(); | ||
update_motors_orders(); | ||
} | ||
|
||
void update_motors_orders() | ||
{ | ||
servomotor.write(constrain(servo_angle, THETA_MIN, THETA_MAX)); | ||
motor_speed = constrain(motor_speed, -SPEED_MAX, SPEED_MAX); | ||
// Send motor speed order | ||
if (motor_speed > 0) | ||
{ | ||
digitalWrite(DIRECTION_PIN, LOW); | ||
} | ||
else | ||
{ | ||
digitalWrite(DIRECTION_PIN, HIGH); | ||
} | ||
analogWrite(MOTOR_PIN, convert_to_pwm(float(motor_speed))); | ||
} | ||
|
||
void stop() | ||
{ | ||
analogWrite(MOTOR_PIN, 0); | ||
digitalWrite(DIRECTION_PIN, LOW); | ||
} | ||
|
||
int convert_to_pwm(float motor_speed) | ||
{ | ||
// TODO: compensate the non-linear dependency speed = f(PWM_Value) | ||
return (int) round(abs(motor_speed)*(255./100.)); | ||
} | ||
|
||
void get_messages_from_serial() | ||
{ | ||
if(Serial.available() > 0) | ||
{ | ||
// The first byte received is the instruction | ||
Order order_received = read_order(); | ||
|
||
if(order_received == HELLO) | ||
{ | ||
// If the cards haven't say hello, check the connection | ||
if(!is_connected) | ||
{ | ||
is_connected = true; | ||
write_order(HELLO); | ||
} | ||
else | ||
{ | ||
// If we are already connected do not send "hello" to avoid infinite loop | ||
write_order(ALREADY_CONNECTED); | ||
} | ||
} | ||
else if(order_received == ALREADY_CONNECTED) | ||
{ | ||
is_connected = true; | ||
} | ||
else | ||
{ | ||
switch(order_received) | ||
{ | ||
case STOP: | ||
{ | ||
motor_speed = 0; | ||
stop(); | ||
if(DEBUG) | ||
{ | ||
write_order(STOP); | ||
} | ||
break; | ||
} | ||
case SERVO: | ||
{ | ||
servo_angle = read_i16(); | ||
if(DEBUG) | ||
{ | ||
write_order(SERVO); | ||
write_i16(servo_angle); | ||
} | ||
break; | ||
} | ||
case MOTOR: | ||
{ | ||
// between -100 and 100 | ||
motor_speed = read_i8(); | ||
if(DEBUG) | ||
{ | ||
write_order(MOTOR); | ||
write_i8(motor_speed); | ||
} | ||
break; | ||
} | ||
// Unknown order | ||
default: | ||
write_order(ERROR); | ||
write_i16(404); | ||
return; | ||
} | ||
} | ||
write_order(RECEIVED); // Confirm the reception | ||
} | ||
} | ||
|
||
|
||
Order read_order() | ||
{ | ||
return (Order) Serial.read(); | ||
} | ||
|
||
void wait_for_bytes(int num_bytes, unsigned long timeout) | ||
{ | ||
unsigned long startTime = millis(); | ||
//Wait for incoming bytes or exit if timeout | ||
while ((Serial.available() < num_bytes) && (millis() - startTime < timeout)){} | ||
} | ||
|
||
// NOTE : Serial.readBytes is SLOW | ||
// this one is much faster, but has no timeout | ||
void read_signed_bytes(int8_t* buffer, size_t n) | ||
{ | ||
size_t i = 0; | ||
int c; | ||
while (i < n) | ||
{ | ||
c = Serial.read(); | ||
if (c < 0) break; | ||
*buffer++ = (int8_t) c; // buffer[i] = (int8_t)c; | ||
i++; | ||
} | ||
} | ||
|
||
int8_t read_i8() | ||
{ | ||
wait_for_bytes(1, 100); // Wait for 1 byte with a timeout of 100 ms | ||
return (int8_t) Serial.read(); | ||
} | ||
|
||
int16_t read_i16() | ||
{ | ||
int8_t buffer[2]; | ||
wait_for_bytes(2, 100); // Wait for 2 bytes with a timeout of 100 ms | ||
read_signed_bytes(buffer, 2); | ||
return (((int16_t) buffer[0]) & 0xff) | (((int16_t) buffer[1]) << 8 & 0xff00); | ||
} | ||
|
||
int32_t read_i32() | ||
{ | ||
int8_t buffer[4]; | ||
wait_for_bytes(4, 200); // Wait for 4 bytes with a timeout of 200 ms | ||
read_signed_bytes(buffer, 4); | ||
return (((int32_t) buffer[0]) & 0xff) | (((int32_t) buffer[1]) << 8 & 0xff00) | (((int32_t) buffer[2]) << 16 & 0xff0000) | (((int32_t) buffer[3]) << 24 & 0xff000000); | ||
} | ||
|
||
void write_order(enum Order myOrder) | ||
{ | ||
uint8_t* Order = (uint8_t*) &myOrder; | ||
Serial.write(Order, sizeof(uint8_t)); | ||
} | ||
|
||
void write_i8(int8_t num) | ||
{ | ||
Serial.write(num); | ||
} | ||
|
||
void write_i16(int16_t num) | ||
{ | ||
int8_t buffer[2] = {(int8_t) (num & 0xff), (int8_t) (num >> 8)}; | ||
Serial.write((uint8_t*)&buffer, 2*sizeof(int8_t)); | ||
} | ||
|
||
void write_i32(int32_t num) | ||
{ | ||
int8_t buffer[4] = {(int8_t) (num & 0xff), (int8_t) (num >> 8 & 0xff), (int8_t) (num >> 16 & 0xff), (int8_t) (num >> 24 & 0xff)}; | ||
Serial.write((uint8_t*)&buffer, 4*sizeof(int8_t)); | ||
} |
Oops, something went wrong.