Skip to content

Commit 95a659f

Browse files
authored
SR2024 - Update Section - Arduino API
2 parents 8ac64fc + 5121c6c commit 95a659f

File tree

7 files changed

+321
-228
lines changed

7 files changed

+321
-228
lines changed

.spelling

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ Plazma
1616
PULLUP
1717
Quarternion
1818
rtui
19+
Arduino
20+
Arduinos
1921
Ruggeduino
2022
Ruggeduinos
2123
Scarzy

_data/sidebar_tree.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ tree:
6060
- url: /programming/arduino/
6161
title: Arduino API
6262
tree:
63+
- url: /programming/arduino/sr_firmware
64+
title: SR Firmware
65+
- url: /programming/arduino/extended_sr_firmware
66+
title: Extended SR Firmware
6367
- url: /programming/arduino/custom_firmware
6468
title: Custom Firmware
6569
- url: /programming/cheat_sheet

programming/arduino/custom_firmware.md

Lines changed: 91 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -3,148 +3,140 @@ layout: page
33
title: Arduino custom firmware
44
---
55

6-
Arduino custom firmware
7-
=======================
6+
# Arduino with custom firmware
87

9-
<div class="info">
10-
This documentation refers to a feature which is only available on the physical robot kits.
8+
<div class="info" markdown="1">
9+
On this page we talk specifically about Arduinos.
10+
However this page is applicable to opening any device that shows up as a serial port.
1111
</div>
1212

13-
The Ruggeduino that came as part of your kit was shipped with a firmware that provides the functionality outlined in the [Ruggeduino](/docs/programming/arduino) page.
14-
You may wish to extend the functionality of this firmware, or completely replace it.
15-
The `sr.robot3` library provides support for three Ruggeduino firmware scenarios:
1613

17-
1. Default SR firmware
18-
2. [Extended SR firmware](#extension): Firmwares that add commands to the default SR firmware.
19-
3. [Completely custom](#completely): Any firmware not derived from the SR firmware.
14+
## Ignoring a device
2015

21-
By default, the [`sr.robot3`](/docs/programming/robot_api/) library assumes that all connected Ruggeduinos are running the SR firmware
22-
or firmware which is compatible with the SR Ruggeduino firmware.
23-
If you're using completely custom firmware, you'll need to tell the kit to ignore the ruggeduino so that you're able to define your own setup logic.
16+
By default when the `robot` object is created it will try to communicate with all Arduinos and will expect them to respond in the way the SR firmware does.
17+
If you want the API to not try connecting to a device we need to *ignore* the Arduino.
2418

25-
[Extension of the SR firmware](#extension) {#extension}
26-
------------------------------
19+
To configure a `Robot` object to ignore a Arduino with custom firmware, you will need to provide it with the Arduino's serial number.
20+
The Arduino serial number is a string of numbers and letters, and is output in the robot log when you run a program on your robot with your Arduino connected.
2721

28-
<div class="warning" markdown="1">
29-
Because the API sets all pins to inputs when the robot is initialised, you cannot set pin modes in the setup function as these will be overridden.
30-
In order to setup pins you can either create a function on the ruggeduino that you call after your robot is initialised or use the [Python functions](/docs/programming/arduino/#pin-modes) to setup the pins.
31-
</div>
32-
33-
You may wish to extend the SR firmware with additional functionality.
34-
This will allow you to continue using the commands already provided by the SR firmware (e.g. `digital_read()`),
35-
which means any existing robot code you have won't need modifying very much.
36-
When you extend the SR firmware, you'll be adding at least one new command to the firmware.
37-
There are almost limitless possibilities of what your commands may do, but here are some examples to give you an idea:
38-
39-
* Talk to an SPI or I2C sensor.
40-
* Read N input pins at the same instant in time.
41-
* Time pulses received from an ultrasound sensor.
42-
43-
There are three steps that you will need to go through to implement and use your custom commands:
44-
45-
### Step 1: Add your command to the Ruggeduino firmware
46-
47-
To extend the SR firmware, you will need to first download its [source code]({{ site.baseurl }}/resources/kit/ruggeduino-fw.ino), and edit it in the Arduino IDE.
48-
When the SR ruggeduino python library wants the ruggeduino to run a command, it sends it a single character to tell it which command to run.
49-
You'll find a `switch` statement in the `loop()` function that processes this command character:
50-
51-
~~~~~ cpp
52-
switch (selected_command) {
53-
case 'a':
54-
command_analogue_read();
55-
break;
56-
case 'r':
57-
command_read();
58-
break;
59-
case 'l':
60-
command_write(LOW);
61-
break;
62-
63-
// ... and so on ...
64-
~~~~~
22+
You'll need the serial number later, so it's best to save it into a variable:
6523

66-
For example, you can see in the above that when it receives an "a" character, it calls the `command_analogue_read()` function.
67-
This function does pretty much what it says on the tin: it reads an analogue pin.
24+
~~~~~ python
25+
from sr.robot3 import *
6826

69-
You will need to add your own entry into this `switch` statement for your new command.
70-
This will need to be represented by a character that doesn't already appear in the switch statement.
71-
Let's say you chose "c"; your entry would look like this:
27+
# Replace this with the actual serial number of your board
28+
ARDUINO_SN = "752303138333517171B1"
7229

73-
~~~~~ cpp
74-
switch (selected_command) {
75-
case 'c':
76-
command_bake_cake();
77-
break;
30+
robot = Robot(ignored_arduinos=[ARDUINO_SN])
7831

79-
// ... all the original entries ...
32+
# The rest of your code
8033
~~~~~
8134

82-
You would then write your `command_bake_cake()` function.
83-
Your command can read additional data from the serial port if it requires additional information to operate.
84-
It can also write a response back to the host (your Python code).
85-
Have a look at the `command_read()` function to see how to do this.
8635

87-
### Step 2: Use your new command from Python
36+
## Opening a serial port
8837

89-
You can send a custom command from your Python code to the Ruggeduino to control your cake-baking.
38+
If you need to communicate with a device, you will need to open its serial port.
39+
If you want the `robot` object to do this and provide a serial port for your use, you will need to do the following.
9040

9141
~~~~~ python
92-
cake_result = R.ruggeduino.command("c")
93-
~~~~~
42+
from sr.robot3 import *
9443

95-
The `cake_result` variable will contain any response from your firmware, if you sent one.
44+
# Replace this with the actual serial number of your board
45+
ARDUINO_SN = "752303138333517171B1"
9646

97-
You're done! You can now use your custom cake-baking firmware!
47+
# Set this to the baud rate that the device communicates with
48+
SERIAL_BAUD_RATE = 115200
9849

99-
If you have multiple Ruggeduino running custom firmware, you can keep track of which one is which
100-
by using the serial number.
50+
robot = Robot(
51+
ignored_arduinos=[ARDUINO_SN],
52+
raw_ports=[(ARDUINO_SN, SERIAL_BAUD_RATE)]
53+
)
54+
55+
# The rest of your code
56+
~~~~~
10157

102-
[Completely custom firmware](#completely) {#completely}
103-
----------------------------
58+
This opens the serial connection to the device and the serial port is now available under:
10459

105-
When configured correctly, the `Robot` object will perform absolutely no serial communications with a completely custom firmware.
106-
We refer to this as *ignoring* a Ruggeduino.
107-
To configure a `Robot` object to ignore a Ruggeduino with custom firmware, you will need to provide it with the Ruggeduino's ID.
60+
~~~~~ python
61+
robot.raw_serial_devices[ARDUINO_SN]
62+
~~~~~
10863

109-
The Ruggeduino ID is a 20 character string of mostly numbers, and is output in the robot log when you run a program on your robot with your
110-
Ruggeduino connected.
64+
<div class="info" markdown="1">
65+
Note that all communications with the serial port is done with `bytes` rather than strings that you will be more familiar with.
11166

112-
You'll need the ID later, so it's best to save it into a variable:
67+
You may need to convert from a string to bytes:
11368

11469
~~~~~ python
115-
from sr.robot3 import *
116-
117-
RUGGEDUINO_ID = "752303138333517171B1" # Replace this with the actual ID
70+
bytes_object = string_object.encode()
71+
~~~~~
11872

119-
R = Robot(ignored_ruggeduinos=["752303138333517171B1"])
73+
or bytes to a string:
12074

121-
# The rest of your code
75+
~~~~~ python
76+
string_object = bytes_object.decode()
12277
~~~~~
78+
</div>
79+
12380

124-
If you need to communicate with the Ruggeduino firmware, you will need its serial device path.
81+
### write
12582

126-
This is accessible from the `ignored_ruggeduinos` dictionary.
83+
`write` is used to send data to the serial port, the function will send whatever you provide.
84+
Putting a `b` in front of a string is a short hand way of creating a bytes object.
12785

12886
~~~~~ python
129-
ruggeduino_device = R.ignored_ruggeduinos[RUGGEDUINO_ID]
87+
# This will send the message "data" over the serial port
88+
# The b in front of the string is not a typo, this is a byte string
89+
robot.raw_serial_devices[ARDUINO_SN].write(b"data")
90+
~~~~~
13091

131-
# The rest of your code
92+
93+
### read
94+
95+
`read` is used to get some data from the serial port, the function will read the number of bytes specified.
96+
If the port times out waiting for data, it may return less bytes that specified.
97+
98+
~~~~~ python
99+
# This will read 5 bytes from the serial port
100+
received_data = robot.raw_serial_devices[ARDUINO_SN].read(5)
132101
~~~~~
133102

134-
The device path will look something like `/dev/ttyACM1`.
135103

136-
You may wish to use pyserial to communicate with the Ruggeduino, in which case you could open it like so:
104+
### read until
105+
106+
`read_until` is used to get some data from the serial port, it will read data until it reads the specified terminator.
107+
If the port times out waiting for the terminator, it may return less data without the terminator on the end.
108+
109+
For example this can be used to read in a single line of data, terminated with a newline character `\n`.
137110

138111
~~~~~ python
139-
import serial
140-
from sr.robot3 import *
112+
# This will read in data until we get to a new line character
113+
received_data = robot.raw_serial_devices[ARDUINO_SN].read_until(b"\n")
114+
~~~~~
141115

142-
RUGGEDUINO_ID = "752303138333517171B1"
143116

144-
R = Robot(ignored_ruggeduinos=[RUGGEDUINO_ID])
117+
### pyserial port
145118

146-
ser = serial.Serial(R.ignored_ruggeduinos[RUGGEDUINO_ID])
119+
The `Robot` uses pyserial to open the serial connection to the board.
120+
If you would prefer you can access the pyserial object directly, like so:
147121

122+
~~~~~ python
123+
serial_port = robot.raw_serial_devices[ARDUINO_SN].port
148124
~~~~~
149125

150126
Refer to the [pyserial documentation](https://pyserial.readthedocs.org/en/latest/) for more information on how to use pyserial.
127+
128+
129+
## Finding other serial devices
130+
131+
If you are using your own serial device that you want to access via a [raw serial port](#opening-a-serial-port), you will need to know its serial number.
132+
To do this we provide a helper function.
133+
Running the below code example will print a list of all the devices connected to the system.
134+
135+
Once you have found your device, and copied the serial number, you can follow the guidance in the [opening a serial port](#opening-a-serial-port) section.
136+
If you need help finding which device is yours contact us on Discord for help.
137+
138+
~~~~~ python
139+
from sr.robot3 import list_ports
140+
141+
list_ports()
142+
~~~~~
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
---
2+
layout: page
3+
title: Arduino extended firmware
4+
---
5+
6+
# Arduino with extended SR firmware
7+
8+
You may wish to extend the SR firmware with additional functionality.
9+
This will allow you to continue using the commands already provided by the SR firmware (e.g. `digital_read()`),
10+
which means any existing robot code you have won't need modifying very much.
11+
When you extend the SR firmware, you'll be adding new commands to the firmware.
12+
There are almost limitless possibilities of what your commands may do, but here are some examples to give you an idea:
13+
14+
* Talk to an SPI or I2C sensor.
15+
* Read N input pins at the same instant in time.
16+
* Time pulses received from an ultrasound sensor.
17+
18+
There are two steps that you will need to go through to implement and use your custom commands:
19+
20+
21+
## Step 1: Add your command to the Arduino firmware
22+
23+
To extend the SR firmware, you will need to first download its [source code]({{ site.baseurl }}/resources/kit/arduino-fw.ino), and edit it in the Arduino IDE.
24+
When the SR Arduino python library wants the Arduino to run a command, it sends it a single character to tell it which command to run.
25+
You'll find a `switch` statement in the `loop()` function that processes this command character:
26+
27+
~~~~~ cpp
28+
switch (selected_command) {
29+
case 'a':
30+
command_analog_read();
31+
break;
32+
case 'r':
33+
command_read();
34+
break;
35+
case 'l':
36+
command_write(LOW);
37+
break;
38+
39+
// ... and so on ...
40+
~~~~~
41+
42+
For example, you can see in the above code that when it receives an "a" character, it calls the `command_analog_read()` function.
43+
This function does pretty much what it says on the tin: it reads an analog pin.
44+
45+
You will need to add your own entry into this `switch` statement for your new command.
46+
This will need to be represented by a character that doesn't already appear in the switch statement.
47+
Let's say you chose "s"; your entry would look like this:
48+
49+
~~~~~ cpp
50+
switch (selected_command) {
51+
case 's':
52+
command_read_sensor();
53+
break;
54+
55+
// ... all the original entries ...
56+
~~~~~
57+
58+
You would then write your `command_read_sensor()` function, which would implement reading the sensor.
59+
Your function can read additional data from the serial port if it requires additional information to operate.
60+
It can also write a response back to the host (your Python code).
61+
Have a look at the `command_read()` function to see how to do this.
62+
63+
64+
## Step 2: Use your new command from Python
65+
66+
You can send a custom command from your Python code to the Arduino to read the sensor.
67+
68+
~~~~~ python
69+
sensor_data = robot.arduino.command("s")
70+
~~~~~
71+
72+
The `sensor_data` variable will contain any response from your firmware, if you sent one.
73+
74+
You're done!
75+
You can now use your custom firmware that can read from a sensor.
76+
77+
If you have multiple Arduinos running custom firmware, you can keep track of which one is which by using the serial number.

0 commit comments

Comments
 (0)