ESP32: Sending short pulses with the RMT

Well that was easy!  About an hour ago I wrapped up a blog post on creating stepper motor driver pulses with the ESP32 using timer interrupts. I added a to do list at the end to look into using the RMT peripheral to do this. It only took about an hour to figure out.

RMT stands for “remote control”. It was designed for things like an IR remote control where tight timing on GPIO is required. The peripheral has a lot of features that make it good for a lot of things. Some people have been using it for the notoriously tight timing of the NEO Pixels.

The documentation is pretty complete on the API, but there are very few examples and tutorials. Most that do exist are for complicated things and not too well commented. This Ebook by Neil Kolban has a good example that my code started from. Look for the section called “RMT – The Remote Peripheral”. Due to my limited knowledge of the RMT, I will only go over my implementation.

Basically you start with two structures…(also see code below)

rmt_config_t config;

This is used to setup the configuration. I set config.clk_div = 80 so that each unit of time in my setup is 1us.

rmt_item32_t items[1];

This is an array of items that represent the outputs transitions that you want. In my case I only want a transition to high for 3us and then transition to low with no duration . Here is the definition of that struct.

typedef struct {
    union {
        struct {
            uint32_t duration0 :15;
            uint32_t level0 :1;
            uint32_t duration1 :15;
            uint32_t level1 :1;
        };
        uint32_t val;
    };
} rmt_item32_t;

Here is my code. I had the pulse repeat with a 1us delay, so that is would be easy to catch some on my logic analyzer.

#include <driver/rmt>

#define STEP_PIN  GPIO_NUM_17

// Reference https://esp-idf.readthedocs.io/en/v1.0/api/rmt.html

rmt_config_t config;
rmt_item32_t items[1];



void setup() {
  // put your setup code here, to run once:
  config.rmt_mode = RMT_MODE_TX;
  config.channel = RMT_CHANNEL_0;
  config.gpio_num = STEP_PIN;
  config.mem_block_num = 1;
  config.tx_config.loop_en = 0;
  config.tx_config.carrier_en = 0;
  config.tx_config.idle_output_en = 1;
  config.tx_config.idle_level = RMT_IDLE_LEVEL_LOW;
  config.tx_config.carrier_level = RMT_CARRIER_LEVEL_HIGH;
  config.clk_div = 80; // 80MHx / 80 = 1MHz 0r 1uS per count

  rmt_config(&amp;config);
  rmt_driver_install(config.channel, 0, 0);  //  rmt_driver_install(rmt_channel_t channel, size_t rx_buf_size, int rmt_intr_num)
  
  items[0].duration0 = 3;
  items[0].level0 = 1;
  items[0].duration1 = 0;
  items[0].level1 = 0;  

}

void loop() {
  // esp_err_t rmt_write_items(rmt_channel_t channel, rmt_item32_t *rmt_item, int item_num, bool wait_tx_done)
  rmt_write_items(config.channel, items, 1, 0);
  delay(1);
  
  
}

Here is a screen shot of the output on a logic analyzer. (Step/dir signals are swapped in the labels)

Conclusion

I think this will work great. This will will be very efficient and rum completely in the background. I will definitely try to move ahead with this method.


If you want to be notified of future blog posts, please subscribe.

ESP32: Step Pulse Experiments with Timers

(Edit: Also check out my better “RMT” way to send the pulse)

I have been playing with the ESP32 microcontroller to see how well it would perform as a small scale CNC controller. The low cost and high performance as well as the built in Wifi and Bluetooth make it very attractive.

One of the challenges is step pulse timing. Most stepper drivers work with a direction signal and step signal. The step signals are a short pulse for each step. If they are too short, the driver will not detect them. If they are too long, it limits the rate at which you can send them.

You first set the direction signal high or low depending on the direction you want the motors to spin. You then send the step pulse. The direction signal has to be stable for a short period of time before the step signal is sent. The process is…

  1. Set direction
  2. Wait a bit (if it changed)
  3. Turn on the step pulse signal.
  4. Wait a bit
  5. Turn off the step pulse signal.

The timing is critical and varies by motor driver. Here is a typical spec.

Here are the specs for a few of the stepper drivers I regularly use.

 Allegro A4988TI DRV8825Toshiba TB6600
Direction Delay200ns650ns?
Step Pulse Delay1us1.9us2.2us

Test Firmware

Typically the firmware motion planner determines when to take a step, then sets an interrupt to occur at that time in the future. This allows the firmware to do other things like interacting with the user and planning future moves while it is waiting for the interrupt.

To simulate a stream of pulses, I created a timer interrupt that would case steps to occur at a constant 5kHz rate. That is onStepperDriverTimer() in the code.

In that interrupt service routine I first set the direction pin. Normally you only need to set it when the direction changes, but it will be easier to see this on a logic analyzer if I change it every time for this test. I then need to wait a little time before setting the step pulse pin. I could use another interrupt to do this, but the time is so short at about 750ns, that it is better to just waste a few cycles. In the CNC software I will only need to do this when the direction changes. That will be at the few beginning of the acceleration when the step rate is the slowest. I do this delay with a few NOP()s. The are “no operations”.

I then setup the the interrupt to end the pulse. That is onStepPulseOffTimer() in the code. I set the step pin after this because those instructions take clock cycles too. I can use those as part of my delay.

When that interrupt occurs, I turn off the step pulse signal. I also turn off the direction in this example. I am only doing it here so I can see that change on the logic analyzer. Normal CNC frmware would just leave it alone because there are typically thousands of steps before the direction is likely to change.

I wrote a program to simulate some CNC firmware so I could play with step pulse timing.

// create the hardware timers */
hw_timer_t * stepperDriverTimer = NULL;  // The main stepper driver timer
hw_timer_t * stepPulseOffTimer = NULL;  // This turns the step pulse off after xx uSeconds

// define the gpio pins
#define STEP_PIN 17
#define DIR_PIN 16

// the step pulse interrupt service routine. 
void IRAM_ATTR onStepperDriverTimer()
{
  // if ... the direction changed from last time (not in this demo)
  digitalWrite(DIR_PIN, HIGH);  // in actual CNC firmware this will go high or low
  for(uint8_t i=0; i&lt;10; i++)
  {
    NOP();  // do nothing for one cycle
  }
  // end if

  // setup the pulse off timer
  timerWrite(stepPulseOffTimer, 0);
  timerAlarmWrite(stepPulseOffTimer, 22, false);  // the alarm point is found by looking at logic analyzer
  timerAlarmEnable(stepPulseOffTimer);  
  
  digitalWrite(STEP_PIN, HIGH); // put it after the timer setup to include the timeto do that
}


// 
void IRAM_ATTR onStepPulseOffTimer()
{
  digitalWrite(STEP_PIN, LOW); // end step pulse 
  digitalWrite(DIR_PIN, LOW); // only here for dem program CNC firmware would leave this until direction change
}


void setup() {  

 pinMode(DIR_PIN, OUTPUT);
 pinMode(STEP_PIN, OUTPUT);

    
 stepperDriverTimer = timerBegin(0, 4, true); // 80Mhz / 4  = 20Mhz// setup stepper timer interrupt ... this will simulate a flow of steps
 stepPulseOffTimer = timerBegin(1, 1, true); // 

 // attach the interrupts
 timerAttachInterrupt(stepperDriverTimer, &amp;onStepperDriverTimer, true);// attach the interrupttimerAttachInterrupt(directionDelayTimer, &amp;onDirectionDelayTimer, true);// attach the interrupt
 timerAttachInterrupt(stepPulseOffTimer, &amp;onStepPulseOffTimer, true);// attach the interrupt
 
// setup the time for the 
 timerAlarmWrite(stepperDriverTimer, 4000, true);  // 20Mhz / 4000 = 5kHz rate ... this is the only one that auto repeats  
 timerAlarmEnable(stepperDriverTimer); 
 
}

void loop() {
  // no loop code required.:
  
}

Results

Here is a picture of my setup.

This is screen shot of what the logic analyzer captured. The upper line is the step signal and the lower line is the direction signal. The direction signal comes on first and then the step pulse signal comes on 0.75us later. The step pulse then lasts for about 2.5us before turning off.

Next Steps

  • I’ll go forward this method to see how well it works in actual CNC firmware.
  • I have been programming in the Arduino-ESP32 environment. This is an easy way to learn about the peripherals and do some quick tests. I may switch to the ESP-IDF  in the future.
  • I would like to investigate the RMT features of the ESP32. It is designed for Remote Controls, but I have heard it is quite flexible and might help with pulse generation.

 


If you want to be notified of future blog posts, please subscribe.

Using The midTbot Controller

The midTbot Controller is a controller for midTbot pen drawing machines. It is sold on my Tindie store. When fully populated, it has the following features.

  • (2) Stepper Motor Drivers for the X and Y axes with microstepping selector jumpers
  • Servo Connector for Pen Lift
  • Arduino Nano Controller
  • 5V power supply
  • (2) Homing switches
  • Bluetooth connector for HC-05 or HC-06 module.
  • Aux power connector for easy access to 5V and 12V power.

Power Supply

You will need a 12V DC power supply with at least 3A of power. The DC plug should be a coaxial 5.5mm x 2.1mm type with center positive. This type of plug is the most common type and should be pretty easy to find.

Microcontroller.

You should use an Arduino Nano compatible controller. The controller bootloader will need to be changed to the smaller Arduino UNO bootloader in order to fit the firmware. I have instructions on how to do this here. If you would like to buy one already modified, I sell them on my Tindie store. Be sure to install the controller in the correct orientation. The USB connector should face the edge of the controller as noted on the silkscreen of the controller PCB.

Stepper Drivers

You will need 2 stepper driver modules. I recommend ones based on the Allegro A4988 controller or the TI DRV 8825 controller. The drivers often come with heatsinks. The current will typically be set low enough that heatsinks are not needed.

You will need to set the microstepping level. I recommend using 1/8 microstepping. That gives a good balance of accuracy, smoothness and speed. You set this using the jumper blocks. Each stepper driver type has its own configuration. Here are the jumper setting for A4988 and DRV8825

Microstep ResolutionA4988 JumpersDRV 8825 Jumpers
FullNoneNone
1/2MS1MS1
1/4MS2MS2
1/8MS1 + MS2MS1+MS2
1/16MS1+MS2+MS3MS3
1/32Not AvailableMS1+MS2+MS3

Note the MS1, MS2 & MS3 labels next to the jumpers.

The orientation of the drivers is very important. You will break the drivers and likely other parts if you insert them wrong. Most drivers have the pins labeled and the the controller PCB has the corner pins labeled. Be sure the labels match. Here are the correct orientations for the A4988 and DRV8825.

You should set the stepper driver output current to the level required by your stepper motors. The midTbot does not need a lot of power. If you set the power too high, the motor could get hot and damage the 3D printed part it mounts to. You set the current by adjusting a potentiometer and reading a voltage. The drivers need to be powered when you do this. You can install them and power the board to do this. Do not connect the motors when adjusting the potentiometer. Each driver will have a small hole with exposed metal. This is the measurement point. The metal adjustment screw of the potentiometer is also a place you can measure. The reference voltage to current formulea are here.

DRV8825 Current = VREF * 2   (Example 0.4V = 0.8A current)

A4988 is a little more complicated because there are different versions. See this page.

Stepper motors:

The controller is designed for NEMA14 motors. Be sure to get 4 wire motors. Just about any size should work, but I prefer to use smaller ones to keep the size and weight down. You will need to attach connectors to them.  Trim the wires to the correct length so they reach the board connectors when installed. Wires colors should be installed as shown.

The wiring legend on the board that shows where to plug in the motors might not be right. It depends on the way the motor manufacturer wired the coils and which stepper drivers you use. You may need to swap them or rotate the connectors 180° if your axes are moving the wrong way. Here is a photo of how mine are wired. Try this first. Note the wire colors and which motor goes to which connector.

Bluetooth

You can add an HC-05 or HC-06 Bluetooth module. They have different connectors, but just match the pin names on both sides. You will need to setup the module to have a baud rate of 115200, N,8,1. I have detail on how to do that here (HC-05, HC-06).

 

 


If you want to be notified of future blog posts, please subscribe.

Using the HC-05 Bluetooth Module

In a previous post I showed how to use the HC-06 Bluetooth module. In this post we will be using the HC-05. They are very similar, but the HC-05 has more features. The ability to be a master is the main feature. A master can create a connection with other Bluetooth devices. In this post we will only being using it as a slave.

The basic module looks like this.

It is typically purchased soldered to carrier PCB with some additional electronics. The HC-05 typically has a 6 pin header, rather than the 4 pin HC-06 header. The two extra pins are state and enable (en). State gives the state of the Bluetooth connection and enable can power down the module by turning off the power regulator. I will not be using the enable. I will use the state to allow programming of the Arduino via Bluetooth.

 

Here is a schematic of the carrier board. Not all carrier boards are the same, though.

The parts on the carrier PCB are pretty basic

  • 3.3V Low Dropout Regulator, which allows you to power it from 3.6V to 6V.
  • An LED to show the mode.
    • Fast Blink = Waiting for Bluetooth connection3.6
    • Slow Blink = In AT command mode
    • Double Blink = Connected via Bluetooth
  • A button to enter AT Command Mode
  • A diode, probably for reverse voltage protection.
  • Various Pull Up/Down resistors and bypass capacitors.

Configuring the HC-05

Like the HC-06, the HC-05 has a AT command mode, but the commands are a little different. The HC-05 is put in the AT command mode by holding in the switch while applying power. It will do a slow blink when in AT mode. AT Mode accepts commands at 38400 baud , N,8,1 using the Rx and Tx pins. You should level shift the Tx out of your Arduino to 3.3V using a resistor divider. Commands are sent with line feed and carriage return appended to the end. Most serial monitors can do this for you including the Arduino Serial Monitor.

Any command that sets a parameter can also get it.

  • Set commands are in this format “AT+CMD=PARAM” like … AT+NAME=FRED to set the name to FRED. Some commands have multiple parameters that are separated by commas.
  • Get commands are in this format AT+CMD?” like AT+PSWD? to get the password. Weirdly, they all seem to work except AT+NAME?.

Here are the commands you needs for slave mode. Remember, each is followed by a line feed and carriage return.

  • AT (This is just a way to test the connection. It will respond “OK”)
  • AT+VERSION? (This returns firmware version info)
  • AT+ROLE=x (for x use 0 =Slave role, 1 = Master role, 2 = Slave-Loop role default = 0)
  • AT+NAME=xxxxx (to change name to xxxxx default=HC-05″)
  • AT+PSWD=nnnn (to change password to 4 digit nnnn default = 1234″)
  • AT+UART=nnnn,s,p (nnnn=Baud, s=stop bits (0=1, 1=2), p=parity (0=None, 1=Odd, 2=Even) Example AT+UART=115200,0,0
  • AT+POLAR=a,b (a=PIO8 (LED), b=PIO9 for both 0=low turn on, 1 = high turn on. (see below for how we use this)
  • AT+ORGL (reset all parameters to defaults)
  • AT+RESET (restarts the HC-05. Will not be in AT mode afterward unless button held”)

Using an Arduino to program the HC-05

We need some hardware to talk to the HC-05. An Arduino will easily do that. Here is a diagram and sketch to do this using an Arduino UNO.

This is the hardware diagram. I show an UNO, but virtually any hardware (Nano, Mega, etc) will work. The HC-05 is a 3.3V device so we need to level shift the Arduino 5V Tx signal down to 3.3V.  The diagram uses a resistor divider to do this. The Arduino should have no trouble reading the 3.3V Tx signal from the HC-05, so we don’t need to shift that.

The State connection through the capacitor is optional. This will force a reboot of the Arduino when a Bluetooth connection is made. More on that later.

BTW: A lot of people don’t bother to level shift and it appears to work fine, at least in the short term 🙂

The Arduino Sketch

Here is the sketch I use. We will be setting up 2 serial links. One link will be from the PC to the Arduino to send the commands from the keyboard over USB.  We also need a serial connection from the Arduino the HC-05. We will use a software serial port for this and can use any remaining pins to do this. HC-05 uses 38400 baud for AT commands, regardless of the what you set it to for Bluetooth operation.  I used 115200 for the PC to Arduino connection. Set the Serial monitor like this.

You can then type AT commands in the Sereial Monitor.

Here is the sketch…

#include &lt;SoftwareSerial.h&gt;

#define SOFT_RX 11
#define SOFT_TX 12

SoftwareSerial hcSerial(SOFT_RX, SOFT_TX); // RX, TX

String fromPC = &quot;&quot;;

void setup() { 
  Serial.begin(115200); // hardware serial for the USB-PC
  hcSerial.begin(38400);  // software serial Arduino to HC-06 (38400 is default)

  // print instructions
  Serial.println(&quot;HC-05 AT Command Programmer V1.2&quot;);

  Serial.print(&quot;For Arduino Rx use pin &quot;);
  Serial.println(SOFT_RX);
  
  Serial.print(&quot;For Arduino Tx use pin &quot;);
  Serial.println(SOFT_TX);  
  
  Serial.println(&quot; -- Command Reference ---&quot;);
  Serial.println(&quot;To Read use '?', Like AT+PSWD?&quot;);
  Serial.println(&quot;AT (simply checks connection)&quot;);
  Serial.println(&quot;AT+VERSION (requests the firmware verison)&quot;);
  Serial.println(&quot;AT+ROLE=x (0 =Slave role, 1 =  Master role, 2 = Slave-Loop role  default = 0)&quot;);
  Serial.println(&quot;AT+NAME=xxxxx (to change name to xxxxx default=HC-05&quot;);
  Serial.println(&quot;AT+PSWD=nnnn (to change password to 4 digit nnnn default = 1234&quot;);
  Serial.println(&quot;AT+UART=nnnn,s,p (nnnn=Baud, s=stop bits (0=1, 1=2), p=parity (0=None, 1=Odd, 2=Even)&quot;);
  Serial.println(&quot;AT+POLAR=a,b (a=PIO8 (LED), b=PIO9 for both 0=low turn on, 1 = high turn on.&quot;);  
  Serial.println(&quot;AT+ORGL (reset all parameters to defaults)&quot;);
  Serial.println(&quot;AT+RESET (restarts the HC-05. Will not be in AT mode afterward unless button held&quot;);
  
  
}

void loop() {
  // Read from HC-05
  if (hcSerial.available()) {
    while(hcSerial.available()) { // While there is more to be read, keep reading.
      Serial.print((char)hcSerial.read()); // send it to the PC
      }   
  }
  
  // Read from PC
  if (Serial.available()){
    delay(10); //     
    fromPC = (char)Serial.read();    
 
    
      hcSerial.print(fromPC); // show the HC-05 responce
      Serial.print(fromPC); // echo it back to the PC
    
  }
}

Arduino Programming over Bluetooth.

Arduinos are programmed over serial via a bootloader. A bootloader is program that runs for a few seconds whenever the Arduino is started. It looks for someone trying to program it. It runs in one part of the Arduino’s memory. If it does not detect an attempt to program the Arduino it switches to part of memory where the last program (sketch) resides. If it does detect an attempt to program the Arduino, it reads the incoming program instructions over the serial port and writes them to that other part of memory where normal programs (sketches) reside. Once the upload is complete it switches to that program and runs it.

Therefore, in order to program the Arduino over a serial connection, you need to trigger a reboot. The Arduino USB creates a full RS232 connection. In addition to Rx and Tx is has other control lines like DTR (Data Terminal Ready). The Arduino uses the DTR signal to force a reset. To reset an Arduino you pull the reset line to ground. The DTR signal out of the USB chip is high when there is no connection and low (ground) when there is a connection.

If we directly connect DTR to the reset pin, the Arduino will be stuck in permanent reset mode whenever a serial connection is open. To correct that, a capacitor is inserted in the circuit. Capacitors block a continuous signal, but pass a quick transition. Therefore the the change from high to low will look like a quick pulse to ground at the reset pin.

Here is what that looks likes on an Arduino Nano schematic. The length of the pulse depend on the value of the capacitor and characteristics of the high to low transition.

The HC-05 state pin will work for this. In its normal mode it is high during a connection. We need that to be low (ground). Fortunately the HC-05 has the Polar command. That allows you to flip that logic. AT+POLAR=1,0 will do the trick. The first parameter is for the LED. We leave that at 1. The second parameter is the state and we switch that from the default of 1 to 0.

I found that the typical 0.1uF capacitor would not generate an adequate pulse to ground, so I bumped it up to 1.0uF. It occasionally does not work when uploading. I think a little less capacitance might be better. The Arduino uses the hardware serial connections for programming, so you use those pins. When programming the Arduino use the virtual serial port you got when pairing the Bluetooth. Do not use Bluetooth and the USB serial port at the same time. Both would be connected to the hardware Rx and Tx and conflict with each other and possibly cause damage.

 

Other Reset Features

You may not care about uploading code over Bluetooth, but some of your sketches may expect that behavior. I have found this with some GCode senders. They open the serial port and expect to see the text Grbl spits out at startup. Without seeing this text, the program wrongly assumes there is a problem and closes the connection.

Video

Useful Links

 


If you want to be notified of future blog posts, please subscribe.

Notes On Using The HC-06 Bluetooth Module

A couple weeks ago, on a whim, I added to add a Bluetooth module to my Amazon cart. I think I paid about $7 for it. I chose the HC-06, because it sounded better than the HC-05. I was wrong, but probably made the right choice. More on that later.

The module came with no documentation, but it was easy to find the default values via web searches.

  • Name: HC-06
  • Password: 1234
  • Baud: 9600

I powered up the module. A single red LED started blinking.

I searched for it with my PC. I saw a new device called HC-06. I was able to pair with the default password. The LED did not change. It continued to blink. I checked my settings and saw this.

I was pleasantly surprised because I thought there was going to be some deep Bluetooth programming involved. A virtual COM is perfect.  I tried opening COM12 using a Serial Terminal. It took a couple seconds, but the LED changed to constant red and the Serial Terminal was happily waiting for me to send stuff. Without anything connected to the TX and RX pins, sending stuff was not going to do anything. I was eager to test with Grbl so that meant changing to 115200 baud.

Changing the default values

You change values on the HC-06 using an AT command set. These are sent to the HC-06 on the RX and TX pins at the current baud rate. The HC-06 is in the mode to accept the commands when it is not paired and connected (blinking red LED).  You cannot use the AT commands over Bluetooth.

There are a lot of AT commands, but the ones we will use are here…

  • AT (it will simply respond “OK”. A good test to see if you are in AT command mode)
  • AT+NAMExxx (Example AT+NAMEFRED will set the name to FRED)
  • AT+PINnnnn (nnnn is a 4 digit password. Example AT+PIN1288 will set the password to 1288)
  • AT+BAUDn (where n is code number for the baud as follows. Example AT+BAUD8 will set the baud to 115200)
    • 1 = 1200
    • 2 = 2400
    • 3 = 4800
    • 4 = 9600
    • 5 = 19200
    • 6=38400
    • 7=57600
    • 8=115200
    • 9=230400
    • A=460800
    • B=921600
    • C=1382400

The commands are sent without a carriage return or line feed and must be sent within a second. If you are using a serial terminal, make sure it is not sending each character as you type it or you are probably not going to get the whole command out within the second. Most terminals have a mode to send the a whole line. The Arduino IDE Serial Monitor works this way. Make sure the terminal settings are correct.

Using an Arduino to setup the HC-06

We need some hardware to talk to the HC-06 using 3.3V TTL. An Arduino will easily do that. Here is a diagram and sketch to do this using the Arduino Serial Monitor.

We will be setting up 2 serial links. One link will be from the PC to the Arduino to send the commands from the keyboard over USB. This will use the hardware RX and TX pins. We also need a serial connection from the Arduino the HC-06. We will use a software serial port for this and can use any remaining pins to do this.

This is the hardware diagram. I show an UNO, but virtually any hardware (Nano, Mega, etc) will work. The HC-06 is a 3.3V device so we need to level shift the Arduino 5V Tx signal down to 3.3V.  The diagram uses a resistor divider to do this. The Arduino should have no trouble reading the 3.3V Tx signal from the HC-06, so we don’t need to shift that.

 

BTW: A lot of people don’t bother to shift the 5v down to 3.3V and it seems to not break anything, at least in the short term 🙂

Here is the sketch I use. By default the HC-06 is set to 9600 baud. If you change via the sketch, you will need to edit the line “hcSerial.begin(9600);” to current baud rate. This sketch strips out carriage returns and line feeds, so you can leave those on in the Serial Monitor.

#include <SoftwareSerial.h>
SoftwareSerial hcSerial(11, 12); // RX, TX

String fromPC = "";

void setup() { 
  Serial.begin(9600); // hardware serial for the USB-PC
  hcSerial.begin(9600);  // software serial Arduino to HC-06 (9600 is default)

  // print instructions
  Serial.println("HC-06 AT Command Programming");
  Serial.println(" -- Command Reference ---");
  Serial.println("AT (simply checks connection)");
  Serial.println("AT+VERSION (sends the firmware verison)");
  Serial.println("AT+NAMExxxxx (to change name to xxxxx");
  Serial.println("AT+PINnnnn (to change password to 4 digit nnnn");
  Serial.println("AT+BAUDn (to change to baud rate #1");
  Serial.println("  BAUD1 = 1200");
  Serial.println("  BAUD2 = 2400");
  Serial.println("  BAUD3 = 4800");
  Serial.println("  BAUD4 = 9600");
  Serial.println("  BAUD5 = 19200");
  Serial.println("  BAUD6 = 38400");
  Serial.println("  BAUD7 = 57600");
  Serial.println("  BAUD8 = 115200");
}

void loop() {
  // Read from HC-06
  if (hcSerial.available()) {
    while(hcSerial.available()) { // While there is more to be read, keep reading.
      Serial.print((char)hcSerial.read());
      }   
  }
  
  // Read from PC
  if (Serial.available()){
    delay(10); //     
    fromPC = (char)Serial.read();    
 
    if (fromPC == "r" || fromPC == "n") {  // don't send carriage returns to HC-06          
      Serial.println();  // echo it back to the PC
    }
    else {
      hcSerial.print(fromPC); // show the HC-06 responce
      Serial.print(fromPC); // echo it back to the PC
    }
  }
}

Using the HC-06 as a virtual serial port

If you want to use it for Grbl, you will need to change it to 115200 baud with “AT+BAUD8”. You can now connect it to your controller Tx and Rx pins. Tx on the HC-06 would go to Rx on the controller.

You then need to pair the HC-06 with the PC using the normal Bluetooth features. It will create 2 virtual COM ports. You need to select the “outgoing” port.   No all programs that use normal COM port can use these ports. When you connect in the program the blinking red light will turn steady red when connected. It take a second or 2.

The Reboot Issue.

Normally Arduinos reboot when you connect. This is due to a trick with the DTR signal. The HC-06 cannot do this trick, so a Bluetooth connection does not reboot the Arduino. This should not be a problem, but some firmwares, like Grbl, send some identifying information at boot. Some senders look for this. They open the COM port and wait for that information. If they don’t see it, they think something is wrong and give an error.

Some senders don’t care and some senders have been using another trick. If they don’t see the information they send a $I command to ask for it.  Ideally all sender will adopt this over time if they want to play with Grbl over Bluetooth and Wi-fi.

The HC-05

There is another device called the HC-05. It is actually more advanced than the HC-06. It can be a master or a slave device. This makes setup a little more complicated, so it was good that I chose the HC-06.  The one thing I want to try is there might be a way to fix the boot issue. The HC-05 might be able to send a connected signal to force that reboot.

 


If you want to be notified of future blog posts, please subscribe.

 

The midTbot. A New Flavor of H-Bot?

H-Bots

There is a family of 2 axis mechanisms called H-Bots. They use 2 motors on a single belt to generate motion in 2 axes. The most basic type is the classic H-Bot. ‘H’ comes from the outline of the belts.

Image from Galil Motion Control

The motors turn the same direction for motion in one axis. They turn opposite directions for motion on the other axis. If only one motor turns both axis will move evenly (like 45°, etc). All other angles are possible with the right drive ratios.

CoreXY

The H-Bot is simple, but imparts some twisting forces on the mechanism under some loads that work against accuracy.  For example, look at left diagram in the image above. The belt is pulling down on the left side of the ‘H’ and up on the right side. This tries to twist the gantry if there is a resistance to the carriage movement in X. CoreXY addresses this by crossing the belts at one end. A longer belt does increase belt stretch issues though.

Image from CoreXY.com

T-Bots

T Bots are the simplest variety and work well with light loads.

I actually played with a T-Bot concept way back in 2011.

The AxiDraw is a good example of a T-Bot.

The midTbot

I was trying to make the smallest and simplest drawing machine with a reasonable work area. T-Bots are pretty simple, but the motors on the ends seemed to waste space. I also wanted integrated electronics. Moving the motors to the middle carriage seemed to solve a lot of these problems. It does add the motors to the mass of the moving parts, but only on one axis and they are directly over the linear bearings. It really has an elegant and smooth look to it. The midTbot name comes from middle mounted motors on a T bot. Here is an image of just the XY mechanism running.

Electronics

The ideal place for the electronics is right by the motors. This will reduce the wiring as much as possible. Putting the homing switches on the middle carriage would further clean up the wiring.

I designed a modular controller that mounts to the top of the middle carriage and under the motors.

The controller will soon be available on Tindie.

I sell on Tindie

Scalability

It is very scalable because you only need to change the rod and belt lengths. No wiring needs to change. The middle mounted motors makes the platform very stable, but if allow the pen carriage to go too far forward, it could tip forward. I think you would need to extend the feet a little forward to counteract that.

Demo

Here is a demo video of the complete machine.

Source Files (Open Source – Creative Commons – Share Alike – Attribution 4.0)

 

 


If you want to be notified of future blog posts, please subscribe.

 

 

Polar Coaster Updates

I made some basic changes to the Polar Coaster lately to make the electronics a little more robust. I added 2 little mounting points to the rear of the base part.

They attach to one side of the Pen/Laser Control PCB. The mounting height allows the use of 12mm standard spacers. You can still use a Raspberry Pi. The overall height is just a little taller.

I also tried printing one with the spoke pockets going all the way through. This reduces print time by almost an hour and is just as strong.

See the files on Thingiverse.

 

I sell on Tindie

 

 


If you want to be notified of future blog posts, please subscribe.

 

 

Getting More Program Space on an Arduino Nano

I recently compiled Grbl with the COREXY features enabled. To my surprise, the upload to my Nano failed because it did not have enough program space. I was surprised because the Nano and Arduino UNO use the same ATmega328p microcontroller. A little researched showed that they use different bootloaders.

Normally you a special programmer to program microcontrollers like Arduinos. You plug the programmer into the ICSP (In Circuit Serial Programming) pins on the microcontroller.

Bootloaders eliminate the need for this by putting the programmer right on the microcontroller. When you start (boot) the microcontroller, the bootloader runs first. It looks for someone trying to load a program. If it does not see that it switches to running the last uploaded program in another part of memory. The only penalty to this is that the bootloader needs to use a small amount of memory and it delays the start of your program a little. The total amount of memory available to the users is the flash memory size (32k for the …328P chip) minus the bootloader. The Nano and UNO use different bootloaders. The Nano uses a 2k bootloader and the UNO uses a 0.5k bootloader.

To get more memory of the Nano we have two options. We can use an ICSP programmer to use all of the memory. This removes the bootloader. The other option is to use a programmer to put the smaller UNO bootloader on the Nano.

Changing the Bootloader

You will need a programmer. you can get any of a dozen types of dedicated programmers, but you can also use another Arduino with a special sketch loaded on it.

How to use an UNO to Program a Nano

Use the Arduino IDE to upload the Arduino ISP (In-System Programmer) sketch to the UNO.

You will need 6 jumper wires. It is helpful to have a few colors to make it easy to verify the connections. They should have male pins on the UNO side and typically female sockets on the Nano side.  These ribbon style jumpers are nice because you can peel off what you need and they have a lot of colors.

Arduino Uno (the programmer) Arduino Nano (the target)
5V 5V
Gnd Gnd
D13 Reset
D10 D10
D11 D11
D12 D12

Install the Bootloader.

Be sure UNO is selected in the boards menu. This will make sure the UNO bootloader is used.

Change the programmer to Arduino ISP in the programmer menu. Remember to return it to current setting, typically AVR ISP, after you are done installing the bootloader.

Now select the Burn Bootloader menu. This will now install the UNO bootloader onto the Nano using the Arduino UNO as a programmer.

Using the Nano.

The Nano should now have the smaller UNO bootloader. When programming from now on, be sure to select UNO in the boards menu. The IDE will no longer be able program it as a Nano. You might want to mark the Nano so you remember this.

Extra Reading…..

How does the USB cable reboot the microcontroller?

In order to program the microcontroller via USB it needs to restart (boot). It does this using a special trick. Arduinos show up as a serial port (COM port).  The Arduino only uses the Tx and Rx signals to transmit data. The USB adapter supports other RS232 signals. The DTR (Data Terminal Ready) signal is used to reset the Arduino. The DTR signal can be controlled by the program uploading the firmware.

Not shown in the schematic is a 1K pull up resistor on the reset pin near the ATmega328p. To reset the microcontroller you pull the reset pin to ground. The uploader program pulls the DTR signal low. The cap passes this change through, causing a reset, but the 1k pull up returns the reset back to the high (run) state. Remember: Capacitors pass changes (AC), but block a steady voltage (DC). 

Why do they use different bootloaders?

I do not know the answer, but it probably due to the fact that they use different USB chips.

 


If you want to be notified of future blog posts, please subscribe.

 

Bus Servo Draw Bot

I wanted to complete a start to finish project with the LX-16A bus servos to do a complete review of their viability for the type of mechatronics projects I do. The low price of the LewanSoul bus servos make them a competitive option over digital servos. I chose to do a remake of the Line-Us clone drawing machine because I would not need to spend too much design time and it would be a good 1:1 comparison with digital servos. Since the bus servos are quite a bit larger, I decided to scale up the machine by 1.5x.

Made My Own Brackets.

I started by buying one servo and it came with brackets. When I went to get more, I noticed the price was lower. I did not realize I was getting these without brackets. These are the brackets you get with the more complete kit.

I requested some 3D models from LewanSoul. They were only able to provide 2D DXF files, but they were easy to convert in Fusion 360. This allowed me to 3D print some brackets. It actually worked out quite well because I was able to thicken up the brackets and integrate some captive square nuts.

They mounted easily to the servos and were plenty strong for this project.

Servo Arms

I made two arms and one short cam for the Z. They were about 4mm thick and had a little pocket that slid over the standard round actuator. They screwed on with the screws that come with the servos. Before mounting anything I turned on the servos and moved them to the center of the range. This put the arms at a known angle.

Support Bracket and Base

The support bracket holds all three servos and there are 2 pockets on the bottom for some shaft bushings.

The base has two shafts pressed into it.

The shafts slide into the bushings and there is a spring to hold the parts together.  The spring prevents the pieces from separating and also provides a little extra pull down force in case the shafts bind a little. The cam provides about 6mm of lift.

Final Assembly

The servos are mounted to the support bracket.

The wires are connected to the servos. They just daisy chain from one servo to the next.

The remaining links are then connected.

Testing

Here is a video of the first run.

Results

I think these are a good alternative to digital servos. They are very strong, easy to mount and accurate. Depending on the design of the controller, using a simple UART might be easier than having multiple PWM signals or extra hardware. The servo’s size might be larger than some machines need but that comes with the higher power.

 

LewanSoul Lobot LX-16A Serial Servo Review

I stumbled upon these LewanSoul LX-16A Servos the other day on Amazon while searching for standard digital servos. These servos are digital serial bus servos. That means they use a serial protocol on a bus rather than a PWM signal. I have used bus servos before, but the $12 price got my attention. That competes well with plain old PWM servos.

Serial bus servos have some real advantages over standard PWM servos.

  • Wiring: The wiring can be a lot simpler because you can put all your servos on a single 3 wire bus. Each servo has 2 connectors to make daisy chaining easier.
  • Higher resolution: The resolution is typically higher. It depends on the way they sense position. These use a high accuracy potentiometer and list 0.24° as the resolution.
  • You can set the speed: You can set a destination and speed for each move.
  • Set the range: You can limit the range of the servo. This is great if the using the full range would crash a joint on your machine.
  • Continuous turn mode: There is a speed adjustable continuous rotation mode on these, but absolute distance moves cannot be done.
  • Motor On/Off: Turn the motor off for manual movement.
  • Feedback: The communication is bi-directional so you can query a servo for…
    • Position: If you manually move a servo, you get its position. This is great for recording “poses” or setting range limits.
    • Temperature: You can read the current temperature of the motors.

Compared to Robotis

I have used the Robotis Dynamixel XL320 servos before but these are a lot stronger and the XL-320 has a weird, plastic rivet, mounting systems that I am not fond of.

Here is a size comparison with a XL-320.

Specs

Spec LX-16A XL-320
Max. Torque 17 kg-cm 4 kg-cm
Resolution 0.24° 0.29°
Range 240° and Continuous Rotation 300° and Continuous Rotation
Speed 62 RPM 114 RPM
Weight 52g 16.7g

Usage

To use the servos you need to use one of their controllers. The most basic controller just converts a USB or TTL serial signal to their protocol. The controller is small and low cost ($10). You can send commands via a USB (Com Port) or via the TTL pins.

Setup Program.

They have a setup program.  The program is Windows only and I had to run it in Administrator mode to get it to work. This makes setting up the servos easy, but you could write your own program if you don’t want to use theirs.

TTL Control

They also provide some Arduino Sketches. They worked fine and are a good place to grab some code if you are writing your own program.  The sketches use the Arduino hardware TX and RX pins. That conflicts with uploading, so you need to disconnect the controller every time you upload. I edited the sketch to use SoftwareSerial on some other pins and that made playing with the code a lot easier.

First Impressions

I found the servos very easy to use and they appear to be strong and responsive. I think they will be a good option for my on my machines.

Next Steps

I want to test these in a real machine. I thought I might try to make a slightly larger version of my Line-Us clone. That would be a good comparison of accuracy. I might try one day build on it tomorrow.  I can probably get a machine designed and built in a day, but the controller programming would need more time.