Projects

Part 4: SAM v1.3

Setting SAM Free

Oliver Higgins

Issue 6, December 2017

This article includes additional downloadable resources.
Please log in to access.

Log in

Like a baby bird ready to leave the nest, we cut the cord and set SAM free.

As the evolution of SAM continues, we are now faced with the challenge of building a way to control SAM remotely. Don't worry, the irony of creating a remote control for a semi-autonomous-machine is not lost on us. But what's life without choices!

How can we create a system that will enable us to send various pieces of data to the unit and then act upon it?

THE BROAD OVERVIEW

Through its development, SAM has been “somewhat” a victim of its intelligence. That is, the intelligence that we can program into it. As we build on the basic principals of SAM, we will reach a stage of needing to exert some level of control in its everyday function. For example, if we were to build a gripper we would need to build in significant feedback mechanisms for the grip itself, in terms of guidance and pressure sensors. At this level, it is much easier to control these elements manually, or rather don’t let SAM do it!

We need to find a way to send instructions to SAM. These instructions may be moving forward, back, turning or even reading from the ultrasonic sensor or activating the gripper. We could connect directly to the computer and send serial commands, but this negates it being able to move around. We could use the IoT idea and create a wireless access point and send data as a HTTP request or similar, but the data that SAM requires is quite simple so this may well be overkill. We need to find a way to send short bursts of data, wirelessly and quickly.

The prototype controller
The prototype controller.

HOW IT WORKS

The SAM robot circuit components remain mostly the same. We will add the functionality to remotely control SAM, similar to any other remote controlled vehicle. To do this will be using the 2.4GHz spectrum using the NRF24L01+ (2.4GHz) transceiver module. These are low-cost short-range data transmitters. We need to use two for this project: one for transmissitting (Tx) and one for receiving (Rx) the data. We will get the information required to build our packet of data from the various buttons and controls. The unit has baud rates (data transfer rates) from 250kps to 2Mbps if used in open space, and at the lower baud rate you may transmit up to 100m. Do be mindful that other devices on the 2.4GHz spectrum may interfere, and reduce the stated range. This module MUST be run at 3.3V; running it at 5V is likely to result in the unit becoming damaged.

Joystick

To feed SAM precise information relating to its movement, we will be using two small “PlayStation” style controllers, which will enable us to specify a precision level of accuracy, and then feed it to SAM. Why would we bother? Well, the alternative is to use a button, which could easily be allocated to “go forward” or “turn right”. The problem with this is that it’s on or off – SAM will only drive at one speed of really fast or slow, depending on what we set in the code. By using the controller, we have the capacity to move SAM at a rate relative to our needs.

The joysticks are comprised of two potentiometers to measure the X and Y movements. This gives us two values that allow us to plot a point in space. The values are read independent of each other, so you do not have to read both the X and Y, nor do you have to implement them together. Here we have one joystick that controls forward movement on the X-axis but pans the servo on the Y.

Buttons

Both joysticks have built in buttons, which can be activated by pushing them down. We have also wired up several standard buttons in testing, but for this project we will just be using the two joysticks. These buttons read high and will float unless you specify the use of the internal pull-up resistor. We have also added in four single buttons, in the classic game configuration and have included them in the circuit diagrams and the transmitter code. The receiver will receive all the codes assigned to the packet, but it’s up you as to whether or not you use them.

ADC

The Arduino can deliver this precise level of control through the use of analogue to digital conversion. On the UNO, there are six pins (A0-A5) that can be used to read values that fluctuate and change, unlike a digital signal that is simply on or off, high or low, 0 or 5V. The UNO uses a 10-bit analogue to digital converter, so this yields a resolution between readings of 5V / 1024 units, or 0.0049V (4.9mV) per unit.

To get a precise location to the Arduino, of where the joystick has been moved, measure the given voltage on the desired pin. It allocates a reference point and gives you the value as a number on that scale. For example, with this implementation the scale is 0-5V. The digital version of this scale is 0-1023, so 0V = the number 0, 5V = 1023. If the joystick is half way and reading 2.5V, then the value is 512. Arduino will give you the 0-1023 scale, as that is the resolution of that port. However, if your required scale is different, say 0-180 degrees, you can “map” the value and use that instead. We are using a map of 0-255 as the motor drive speed is controlled via a scale of 0-255. The UNO has a 10-bit ADC on board. To get this, we just need to use the analogRead function.

map(analogRead(A0), 0, 1023, 0, 255);

Mapping the value

int val;
val=analogRead(A0);
Serial.println(Val)

We map the value to a range that suits our needs. Our PWM control on the Rx is 0 to 255 so by mapping the value now, we are able to feed that value straight to the PWM anlaogWrite on the other side.

Finally, we get all the data from these inputs, assemble them into a packet, and pipe them to the transmitter.

amplitude grapth

Analog to digital conversion: Here we are demonstrating the change in voltage from a potentiometer (variable resistors) that causes the voltage to increase or decrease creating our wave.

Analog to digital conversion grapth

To record this wave or signal, we first need to measure it. This is referred as sampling. We establish a relative time frame that we can sample our data, then measure the height or voltage of the signal. We have assigned the value below each sample.

Analog to digital conversion grapth

To playback or recreate this signal we need to get each piece of data and then recreate the voltage to that level. We end up with a stepped signal that recreates the original voltages.

THE BUILD

Original SAM Parts LISTs for v1.0-1.2:

Parts Required: Jaycar Altronics
2 x Arduino UNO R3 or Mega 2560 XC4410 Z6240
1 x Ultrasonic Module XC4442 Z6322
1 x L298n Motor Control Module XC4492 Z6343
1 x 4WD Chassis & Motor Kit KR3162 K1092
1 x SG90 Servo with Screws and Horns YM2758 Z6392
1 x 8x8 LED Matrix Module XC4499 Z6362
1 x 8AA Battery Holder PH9209 S5034
8 x AA Batteries SB2333 S4955B
2 x 2.5mm Screws
2 x 20mm M3 Bolts
4 x M3 Nuts

PARTS LIST FOR v1.3:

Additional Parts Required: Jaycar Altronics
2 x Joystick Modules XC4422 Z6363
2 x NRF24L01+ XC4508 Z6361
1 x 3D Printed Radar Head
1 x 3D Printed Body (for UNO R3 or Mega 2560)
1 x NRF24L01+ STL File
Optional: Jaycar Altronics
4 x Push Button Momentary Switches SP0724 S1098
4 x 10K Resistors RR0596 R7249

You'll require jumper wires and standard prototyping hardware.

BUILDING THE CIRCUIT

For this build, we recommend that you build the Tx and Rx modules, then test before moving on to the main build. We would not recommend using a breadboard with the NRF24L01+ module, but rather jumper it directly to the Arduino. If you have a spare UNO or the original SAM, please use that. Sometimes the modules can be a bit difficult to get talking to each other, and we want to eliminate any other possible issues to make sure that it works.

The NRF24L01+ 2.4GHz transmitters used in the project can be a bit fickle. There are many little things such as making sure you are using the 3.3V line or making sure the module pins are connected correctly. However one of the leading issues that you may encounter is due to the signal spectrum spread itself. The units operate in the 2.4GHz band. This particular frequency is part of what is known as the industrial, scientific and medical (ISM) radio bands. Within it, you will find cordless phones, NFC, Bluetooth and wireless networks. As such our houses are full of these signals and it can dramatically decrease the range and reliability of these signals. If you have any issues with inconsistent or difficult transmission then systematically remove or power down these devices. Wifi is often a culprit, but many interference issues can be resolved through changing the channel in your router settings.

circuit

Tx

To build the transmitter or control unit, you will need at a minimum the UNO (or Nano), two Joystick modules and one NRF24L01+ module. We have also included in the circuit diagram four push buttons switches. These buttons do not have any direct action on SAM’s programming at this point in time. They are however included in the data packet that the transmitter sends. SAM receives this information but at this stage ignores them. This can be used to trigger anything from a single LED to a flamethrower. To assemble the transmitter we first connect up the Tx module first, checking that you have 3.3V to the NRF24L01+, remember 5V is more than likely to render it useless. The Ardunio UNO has its 3.3V line right next to the 5V line so please double check this before applying power to the module. Next we hook up the two joystick modules, these should be marked, X, Y and SW (Switch) in addition to GND and VCC. Joystick A’s X goes to the A0 pin and Y to the A1 pin. We repeat with Joystick B’s X connection going to A2 and Y to A3. Finally we hook up Joystick A’s SW to pin 6 and Joystick B’s SW to pin 9. This is all we need for this implementation of SAM. For bonus marks we have added extra buttons to the build, to connect them you will need four x10k resistors and four push buttons. We chose these particular ones to give it the classic retro gaming feel. Connect one side of the push button switch to the 5V line, next take your 10k resistor and connect to the other side of the switch and to ground. Next connect a jumper from the resistor on the switch side and connect it to pin 2. Repeat another three times. Remember, you do not need these to make SAM move.

3.3v VCC NRF24L01+
00 NC
01 NC
02 Button 1
03 Button 2
04 Button 3
05 Button 4
06 Button Joystick A
07 NRF24L01+ CE
08 NRF24L01+ CSN
09 Button Joystick B
10 NC
11 NRF24L01+ MOSI
12 NRF24L01+ MISO
13 NRF24L01+ SCK
A0 Joystick X A
A1 Joystick Y A
A2 Joystick X B
A3 N Joystick Y B C
A4 NC
A5 NC
assembly

Rx (SAM)

Please note that there is a number of pin assignment changes with SAM compared to the last version. We would recommend reviewing the unit or starting again to ensure that they are in the correct assignments. The chassis build stays the same, but we have added in a holder for the NRF24L01+ module. This should snap snuggly, but the various modules we tested did have some variation. We have included the OBJ file as well as the STL, which will enable you to slightly edit the holder if need be. We have included a single snap STL file as well to test before printing the entire chassis. The LED matrix goes together using the two M3 screws and nuts (please see issue 005 for reference). Place the Uno on the chassis and snap the motor board into place. Connect the motors as per diagram then add in the jump over to the Arduino. Next, connect up the NRF24L01+ module. Once again, please be mindful that the NRF24L01+ is 3.3V. Double check this as the 3.3V line in right next to the 5V line on the UNO. Connect the NRF’s CE and CSN to pin 7 and 8. Next connect MOSI, MISO and SCK to 11,12 and 13. Finally make sure you have ground and that you have used 3.3V. Note that you do not use the IRQ pin on the NRF24L01+. At this stage we would recommend that you make sure that the transmitter and receiver are both working.

Once we have the receiver in place connect up the servo and locate the SERVOSETUPFILE from SAM v1.2. Assemble the Ultrasonic sensor leads first to the ultrasonic unit and then fit it to the ultrasonic 3d printed caddy. Upload and run the servo file which will align the servo to the 90 degree position. Place the caddy on and screw in place. Connect the ultrasonic unit to the Uno, connecting TRIG to pin A2 and ECHO to pin 3. Our last task is to connect the motor board to the UNO. You can connect in any order you wish however the easiest way is to work backwards on the moto driver board. Start with ENB, IN4, IN3, IN2, IN1 then ENA. This save trying to push jumpers between pins.

3.3v VCC NRF24L01+
00 NC
01 NC
02 NC
03 US Echo
04 Motor IN3
05 Motor ENA
06 Motor ENB
07 NRF24L01+ CE
08 NRF24L01+ CSN
09 Motor IN4
10 Motor IN1
11 NRF24L01+ MOS
12 NRF24L01+ MISO
13 NRF24L01+ SCK
A0 Motor IN2
A1 Servo
A2 US Trig Pin
A3 LED MATRIX CLK
A4 LED MATRIX CS/td>
A5 LED MATRIX DIN

If you are using the Mega 2560, please note that there are some pin differences for the NRF module:

Mega 2560 UNO/Nano
CSN 8 8
CE 7 7
SCK 52 13
MOSI 51 11
MISO 50 12

THE CODE

Libraries

You will need to install the RF24 library to enable the use of the NRF24L01+.

Upload the code to both units. Be mindful that you select the right board for the circuit you have built. The code is ready to run, but you will find that line 34 has one option to enable/disable SAM’s intelligence. This is set by default as 0, which is off. SAM will operate like an RC car until you hold down Joystick A’s button for one second.

At this point, we recommend that you power up the Tx module that you have already built and open the serial monitor on SAM. If your connection works, you will see a data stream in the serial monitor (9600bps), if the stream is there but the values are 0 then it means that a transmission has been received. Check your Tx for connections to the joysticks and buttons if used.

If all is working take this opportunity to open up the serial plotter and you will be able to see the data graphed.

127,129,1,124,127,1,0,0,0,0 STP
127,129,1,124,127,1,0,0,0,0 STP
127,129,1,124,127,1,0,0,0,0 STP

This shows the output of the data packet that we are sending. The first two numbers are the A joystick, and the X and Y coordinates. The third is Joystick A’s press button. Numbers 4,5 and 6 are the same, but for Joystick B. The remaining four numbers are the on/off status of our optional buttons. The final three letters/text indicates SAM’s current state. In this case, it’s stopped.

Note: if you get nothing, it’s not necessarily because the Rx circuit is not working, as it only outputs when it gets a radio packet. So start by checking your Tx circuit.

graph

Assuming it all tests fine and you are getting the outputs, power up SAM’s motor driver, and let’s go. To use SAM just move the joysticks around. Joystick A controls SAM’s forward motion, and left/right will move his head. Move Joystick B left and right to make SAM turn. Note: we have coded it so that even if you are going forward or back, the turn will override the command.

Push down on Joystick A to activate the internal push button, which activates the autopilot. This can be a bit finicky at times but due to the nature of the data transmission, we cannot use an interrupt to alter the machine state. Instead, we need to wait until the loop controlling the ultrasonic scan is complete. This means that the data can be missed due to timing, such as when SAM sees an object and is trying to avoid it.

TX Code:

const byte buttonGreen = 2; 
const byte buttonBlack = 3; 
const byte buttonYellow = 4; 
const byte buttonRed = 5; 
const byte buttonJoystickA = 6; 
const byte buttonJoystickB = 9;

Radio setup and use

radio.begin(); 
radio.setPayloadSize(32); 
radio.openWritingPipe(address);  
radio.setPALevel(RF24_PA_MAX); 
radio.setDataRate(RF24_250KBPS); 
radio.stopListening();
int potValue0 = analogRead(A0); 
packet[0] = map(potValue0, 0, 1023, 0, 255); 
int potValue1 = analogRead(A1); 
packet[1] = map(potValue1, 0, 1023, 0, 255); 
packet[2] = digitalRead(buttonJoystickA); 
… 
packet[8] = digitalRead(buttonYellow); 
packet[9] = digitalRead(buttonRed); 
radio.write(&packet, sizeof(packet));

RX Code:

The receiver code is quite straightforward. We need to initialise the radio as per the Tx, and we need to make sure that the baud rates are identical, otherwise the data will not come through correctly. In this case, we have reciprocated the 250kbps baud rate with the line: radio.setDataRate(RF24_250KBPS).

The opening line starts the radio object, then opens the radios reading pipe to establish a data connection (we would set up a second pipe if we wanted bi-directional communication), before issuing the start listening function.

Radio Setup

radio.begin(); 
radio.openReadingPipe(0, address); 
radio.setPALevel(RF24_PA_MAX); 
radio.setDataRate(RF24_250KBPS); 
radio.startListening();

This is the code that drives the motor board. Each time through the loop we get the values from the data stream that work out what we need to do. We use a series of “if” statements. You will note first, that for packet[4] (this is our left/right code) it comes before the forward / back code. This means it will always override the forward/back movement. This is so that when controlling SAM, if you are driving it forward then issuing a left turn, it will appear as though it just turns left. If we did it the other way, then the forward command would always override turning the unit, and you would be forced to stop, turn, and recommence going forward.

As the values read from the joysticks is inaccurate around the middle of their travel, we have created a deadspot. Without this the values read may fluctuate by little. We made the dead spot quite large to ensure that we could test effectively, but please see how close you can get before it causes a problem.

if (packet[4] > 140) { 
    motorSpeed = packet[4]; 
    turnRight(); 
  } 
  else if (packet[4] < 105) { 
    motorSpeed = 255 - packet[4]; 
    turnLeft(); 
  }  else    if (packet[0] > 140) { 
    motorSpeed = packet[0]; 
    forward(); 
  } else if (packet[0] < 105) { 
    motorSpeed = 255 - packet[0]; 
    backward(); 
  } 
  else { 
    stopAll(); 
  } 

If you wired up the motors backwards, you have two options: rewire them or simply change the code around to reflect this. We have put in some commented out lines in the movement code to make this easy. You may find from testing to installation, that your joystick controls are inverted. Use this same method to modify the direction.

WHERE TO FROM HERE

A NOTE ON SAM’S INTELLECT: With the addition of control and scanning, ultrasonic SAM is much smarter than the previous version; however, upon a continued soak test, it was found that with this current software SAM would often get “stuck”. The unit would not bump into things, but as things got closer, the system would slow down the movements to the point where the motors struggled when low in the torque range. Careful testing of your unit, power supply etc. could yield different outcomes, but take the time to modify either SAM’s speed setting, or the multipliers that slow him in the slow turns.

BUIDLING A CASE FOR THE CONTROLLER: We experimented with building a case for the controller, even going down to using a Nano. By the time you added in batteries, the NRF24L01+, the Nano, joysticks and the buttons, it becomes quite large. There are quite a few gamepad options that are now available, which would probably be a more straightforward way of getting it off the breadboard. Alternatively, you can use Tx units such as the Syma X5SC and its library, thus saving considerable time in the development of a control unit (but where is the fun in that?).