NXT Automation Implementation Introduction
Author: Hashim H., Email: hameeh1@unlv.nevada.edu
Date: Last modified on [11/23/24]
Keywords: NXT, Teleoperation, Automation

Motivation and Audience

The following tutorial has the motivation of documenting a means of wireless communication to a LEGO NXT module for the purpose of automation with a concentration on mobile robots. This tutorial assumes:

Parts List and Sources

Software

Setup

Step 1 [Teleoperation Verification]

Follow the instructions within the “LEGO NXT Teleoperation Introduction” tutorial and verify the NXT module can drive motors using either the Playstation 2 Controller or a controller compatible with the Brooke Translation peripheral (operation detailed in following section). Verify the mobile robot platform built prior to the tutorial’s remainder.

Step 2 [Brooke Wingman PS2 Setup]

The Brooke peripheral requires provision of a 5V voltage source, which the NXT module in many cases is incapable of providing. In order to remedy this, utilize a buck converter/step down converter to translate a battery of choice’s voltage (12V LiPo demonstrated) to 5V delivered through an attached breakout micro USB cable.

Verify operation of the Brook peripheral on a functioning NXT module by powering on the module, connecting the 5V power supply if seen necessary, and using a compatible Logitech F710 wireless controller (if not immediately available, the linked page lists all compatible controllers)

Step 3 [Communication]

Disassemble the Logitech F710 controller. Observe the wireless transmitter soldered onto the mainboard, with connections tied to input(s) as seen below and further documented here (required reading). This transmitter may be used connected to the mainboard (pictured) or desoldered and connected to power via the specified pins for a more permanent connection.

It is important to note that each connection handles a voltage of up to roughly 2.1V, with analog inputs accepting any value between 0V-2.1V, so as to not provide excess current. To verify, utilize a multimeter to measure input voltage relative to ground for any given pin. Measurement is additionally recommended in the case of analog input to determine voltage output for desired value(s). Power and voltage may be provided through use of a microcontroller (ESP32 used).

Step 4 [DAC & Power Delivery]

Although constant 3.3V or 0V voltage can be directly output by the microcontroller pins, use of PWM for analog equivalence is not permitted by the wireless transmitter due to signals at every duty cycle being read in real time with a very high sampling rate. A Digital to Analog Converter (DAC) is then required to provide an analog voltage to the transmitter.

A very simple DAC can be made from a Resistor-Capacitor (RC) circuit network. The resistor and capacitor capacitor values are 1kΩ and 100μF respectively. As shown in the figure below, source voltage is connected in series with the resistor in turn connected in series with the capacitor, with the positive end of the capacitor being the analog output voltage.

Use the described circuit for any analog input, using a multimeter on the leg of the capacitor relative to ground to verify constant voltage output between 3.3V-0V as output by a given PWM pin on your microcontroller. Read the respective DAC theory section to learn about how you can reconfigure or iterate upon this circuit.

Step 5 [All Together Now]

At this point it is assumed that wired connections have been made to the desired inputs and respective pins on the microcontroller in correspondence with the input and action within the NXC code onboard the NXT module (refer to “LEGO NXT Teleoperation Introduction” tutorial), whether direct or going through the DAC for analog inputs. It is recommended that the utilized microcontroller cycle through all PWM outputs to verify the DAC’s functionality prior to implementation.

With the NXT module powered on and the desired movement program selected on the module, send voltage through the microcontroller to move the connected motor(s) in some way. This may be done using a case statement regarding external input (covered in more detail in the programming section) or simply assigning a particular output to a desired pin. Consider the case of analog input for the joysticks wherein neutral position is roughly 1V output rather than 0V.

Programming

The following is an example of a simple of a varied PWM output for the purpose of analog motor control:

simple_variation.ino
  1. //constnat instantiation for pins & starting speed(s)
  2. const int yright = 5;
  3. const int yleft = 4;
  4.  
  5. const int button = 0;
  6.  
  7. int speedRight = 75;
  8. int speedLeft = 75;
  9.  
  10. //Setting up pins to be output & setting analog joystick value to neutral
  11. void setup() {
  12. pinMode(yright, OUTPUT);
  13. pinMode(yleft, OUTPUT);
  14. pinMode(button, OUTPUT);
  15. analogWrite(yright, speedRight);
  16. analogWrite(yleft, speedLeft);
  17. digitalWrite(button, LOW);
  18. }
  19.  
  20. void loop() {
  21. //iterates through voltage values to vary speed, with an action performed following each iteration
  22. for(int speed = 0; speed < 200; speed++){
  23. analogWrite(yright, speed);
  24. analogWrite(yleft, speed);
  25. delay(100);
  26. Serial.println(speed);
  27. }
  28. digitalWrite(button, HIGH);
  29. delay(100);
  30.  
  31. }

Data may be passed from external sensors/devices such as cameras or even motion capture to inform the NXT module’s movement. In order to communicate with the microcontroller, the given device(s) are ideally able to run through a script containing some form of serial communication. Used in this case is the Python pyserial library. Following installation, it is recommended that this tutorial be followed to verify communication between a python script and the script running on the microcontroller. Using this as a base, we may create a more robust stimulus-based movement.

The following code shows an arduino ino file with serial communication used to inform motor speed for a mobile robot NXT:

mobile_starter.ino
  1. //instantiates pins & speed(s)
  2.  
  3. const int yright = 16;
  4. const int yleft = 17;
  5.  
  6. const int button = 18;
  7.  
  8. int message;
  9. int stop = 75;
  10. int speedRight = stop;
  11. int speedLeft = stop;
  12.  
  13. //Setting up pins to be output & setting analog joystick value to neutral
  14. //Starting serial for script communication
  15. void setup() {
  16. Serial.begin(115200);
  17. Serial.setTimeout(1);
  18. pinMode(yright, OUTPUT);
  19. pinMode(yleft, OUTPUT);
  20. pinMode(button, OUTPUT);
  21. analogWrite(yright, 90);
  22. analogWrite(yleft, 90);
  23. digitalWrite(button, LOW);
  24. }
  25.  
  26. void loop() {
  27.  
  28. //when communication is not actively occurring, use last defined speed value
  29. while(!Serial.available()){
  30. analogWrite(yright, speedRight);
  31. analogWrite(yleft, speedLeft);
  32. }
  33.  
  34. message = Serial.readString().toInt();
  35.  
  36. //case statements with edge cases
  37. //if the "message" value is within the defined voltage range, it will be mapped accordingly
  38. //if the "message" value outputs 300, stops robot and performs action
  39. if(message != 0){
  40.  
  41. if(message > 0 && message < 200){
  42. speedRight = stop + message;
  43. speedLeft = stop - message;
  44. }else if(message < 0){
  45. speedRight = stop + message;
  46. speedLeft = stop - message;
  47. }else if (message = 200){
  48. speedRight = 125;
  49. speedLeft = speedRight;
  50. }else if (message = 300){
  51. speedRight = stop;
  52. speedLeft = stop;
  53. digitalWrite(button, HIGH);
  54. delay(250);
  55. digitalWrite(button, LOW);
  56. delay(250);
  57. digitalWrite(button, HIGH);
  58. delay(250);
  59. digitalWrite(button, LOW);
  60. }
  61.  
  62. //message will print to terminal of external ide
  63. Serial.println(message);
  64. Serial.println(speedRight);
  65. Serial.println(speedLeft);
  66. }
  67.  
  68. }

Theory

DAC

The RC time constant (τ) for an RC circuit is a value indicative of the rate of growth or decay of a capacitor’s charge in a circuit in seconds obtained from the product of the simplified resistance and capacitance values of a given circuit network (τ = RC = 1/(2πfc) [S]).

A large time constant as derived from the provided values results in a somewhat slow, but consistent signal proportional to the output duty cycle as shown below. This means that consistency and accuracy may come at the cost of latency if desired to keep the network simplified as presented.

Given the provided configuration, heightening either the resistor or capacitor value will lead to a greater degree of latency and more accurate analog voltage, and lowering these values will see these effects inverted. More complex capacitor networks may be utilized to remedy these issues, though are beyond the scope of this tutorial. It is recommended that external research be done regarding such networks prior to implementation.

Final Words