Lumi

Update 3/29/2016

I’ve begun re-writing the entire program as a Windows App. Not really my choice. It seems the BluetoothLE API Microsoft has thrown together (for-real-doh, it’s super bad) is most easily adopted under the Windows Universal App toolchain.

Anyway, here’s the resting space of the new projects

Lumi

Lumi for Desktop

Where I come from they having a saying: “Video or it didn’t happen.” I’ve always liked that saying. It means we have to put our work where our typing is. Here is a video of the uploader I wrote to interface with the TinySafeBoot AVR two-wire (UART) bootloader.

It was written with the idea a serial connection could be directly opened from the computer using Bluetooth 4.0. Or, if we get super fancy, using WiFi. On the receiving end, connected to the AVR, would be an HM-10 or an ESP8266 respectively. This would allow direct wireless uploading of Arduino sketches (or Atmel studio hex files) to the targeted Arduino (or AVR, if you will).

It has a couple of kinks, but I’m fairly pleased with it.

For a little more information on the projects:

http://ladvien.github.io/robots/tsb/

The whole projects is named after my friend Lumi who passed away last year. Amazing man with good taste in photography subjects. :)

Source Code:

https://github.com/Ladvien/Lumi_TinySafeBoot_Uploader

TinySafeBoot, Arduino, and Wireless Upload to ATtiny85

The Dream

I’ve dreamed of a PCB with everything: uC, H-bridges, PSU, Lipo charger, inductive power collector, and a wirelesss device which would allow wireless uploading to the uC. A platform I could use for robotics and wearable projectss alike. Most of these features I have solved, yet one which I believed to be ever elusive to a hacker is wireless uploading. I’ve had lot of failed attempts, some as painful as writing my own uploader for the LPC1114, others as “simple” as hacking away at the Arduino IDE source. However, I’ve found a combination which brings me a bit of hope: TinySafeBoot, Arduino IDE, and most Atmega and ATtiny Atmel chips.

TinySafeBoot

TinySafeBoot is a pretty neat GPL projects which is around 500 bytes. It is a bootloader which allows selection of any two pins as RX / TX for two-wire communication (it also has a one wire protocol). And it has a serial communication protocol.

TinySafeBoot

The feature which makes TSB such a great choice for wireless bootloading is its serial protocol. Unlike the hardware protocol Arduino uses, serial communication allows the remote device to control the bootloaders workflow without flipping any hardware pins. Contrast with the Arduino’s bootloader (I think it’s optiboot now?) which focuses on resetting the device repeatedly to activate the bootloader.

The hardware approach doesn’t work for quick, remote hardware resets. With the serial lag, the Arduino bootloaders are often comfortably booting an existing program by the time the first byte of a new program is reaching the RX pin. Also, there is no quick (sub 400ms) way to flip pins on my focused wireless devices, the HM-1X and ESP8266. In short, either the Arduino bootloader or software would need to be hacked; neither, which I’ve had the time to do.

There are other chip possibilities. I spent a lot of time trying to write a wireless uploader for the LPC1114. However, I do not yet have the skill level to finish it (I’ve not given up on it). There is also a psychological hangup working with the LPC1114. Its documentation. It is not that the docs for the 1114 are so bad, it is the docs for Atmel (makers of the Arduino heart) are so much better. This makes solving the wireless upload dilemma much more beneficial if it were solved for Atmel chips. Well, at least for a hacker like me who does not yet have the skill to move quickly through rougher documented chips. Honestly, it’s about time–I’ve only so much and sometimes it is about getting a projects finished rather than what I might learn (blasphemy, right?).

Of course, TSB has other features such as auto-bauding and password protection, etc. It’s not perfect, but I like it for its simplicity.

Getting TSB Setup

I have tested TSB on three devices, the ATtiny85, ATmega328P, and ATtiny1634. However, the ATtiny1634 didn’t work.

There are two parts to TSB,

  1. Firmware
  2. Software

We are only going to download the software which allows you to generate “custom” firmware for whatever chip you are targeting.

From here on I will be demonstrating getting TSB going on an ATtiny85.

ISP

First, we will need an AVR ISP. Long ago I bought an AVR-ISP MKII which I used in combination with Atmel Studio 7. This will allow us to burn the bootloader and set the fuses. If you do not have an official AVR-ISP you can, theoritically, use AVRdude through the Arduino IDE in combination with an Arduino as an ISP programmer.

So, either,

  1. AVR ISP MKII
  2. Atmel Studio 7

Or

  1. Arduino IDE
  2. Arduino Uno ISP

Either way, once we have our ISP setup we will connect it to the ATtiny85 like,

One note about the above breadboard. There is a momentary switch connected in series with the RESET pin,

PB5<--->Switch<--->GND

This will allow us to easily reset the ATtiny85, which is needed to put the TSB into bootloader mode.

Notice the RX / TX will. They are not part of the ISP. They will be our bootloader’s TX / RX pins when the bootloader has been burnt.

Bootloader Creation

Now, to generate the bootloader.

If you haven’t, download the software, extract it to a workspace, and open that workspace in the command-line. The TSB software is CLI only.

Now enter the following,

C:\TSB_workspace>tsb tn85 b3b4

TSB then should generate a hex file titled something like,

tsb_tn85_b3b4_20150826.hex

This hex file will be our bootloader customized for our particular AVR, the ATtiny85.

To breakdown the TSB command,

  • tn85 tells the TSB SW we are looking to install this firmware on an ATtiny85. If you need to look up a chip code you can find it in a file in the TSB workspace titled “devices.txt”
  • b3b4 tells the TSB SW you want to use PB3 as RX and PB4 as TX. I chose these as pins since they are not being used by the ISP. Note, having the ISP and UART connected to the same pins will cause problems.

Bootloader Burning

To burn the newly generated bootloader you will need to have your ISP connected to the ATtiny85. First, check the fuses of your chip. According to the TSB website we need to have the following fuses set,

ATtinys:

  • SELFPRGEN must be set to enable flash writes from firmware, e.g. TSB
  • BODLEVEL should be set to avoid flash corruption during unsafe device power-up.
  • LOCKBITS may be set to MODE 3 for enhanced security (i.e. serious password protection intended).

ATmegas:

  • BOOTRST activated lets the MCU jump into the Bootloader Section (rather than $0000) with every hardware Reset.
  • BODLEVEL should be set to avoid flash corruption during unsafe device power-up.
  • BOOTSZ=10 or BOOTSZ=11 to reserve 512 bytes for a Bootloader Section.
  • BLB to MODE 2 or 3 protects Bootloader Section from undesirable write access by firmware.
  • LOCKBITS may be set to Mode 3 (LB-Mode 3) in a security environment.

Using Atmel studio, go to Tools-->Device Programming select your programmer (AVR ISP MKII for me), select the ATtiny85, and hit apply. Now, go to Fuses and make sure they are set to the following for the ATtiny85.

If you need to set the fuses using an Arduino-as-ISP, well, I’m not sure I’ve ever done that, but here’s an article that seems legit,

Once the fuses have been set it’s time to burn the bootloader. Using the Atmel approach, go to Tools--Device Programming and click on Device Signature, this will allow the ISP to see if the chip is ready for uploading. Once the chip is verified, go to Memories and click on the ellipses and select your hex file,

Then hit Program. With luck, your bootloader will burn and there will be much rejoicing.

To make sure the bootloader was burned correctly connect your ATtiny85 directly to a USB-to-UART. Open a serial terminal and connect at any baud rate 9600. Hit reset on the ATtiny85 and then quickly (within 2 seconds) send the @ in the serial-terminal. If the bootloader has been burned the ATtiny85 should reply with TSB followed by device data.

Wirelessly uploading

Here’s the fun part. I hooked up my ATtiny85, 2 x HM-10 modules, and an FTDI chip to a PC–like below,

To see if you everything is working, open a serial terminal program. I’m a little partial to this one: HM-1X Aid. Connect the your USB-to-UART using the serial terminal at 9600bps. Once you are connected, press the reset button on your ATtiny85 and send the character @ from your terminal several times. If everything is setup correctly the chip should reply with, TSB followed by device information. If it doesn’t reply, a few things to check.

  1. Test your wireless connection. I had to make sure the Bluetooth devices had paired and the Bluetooth device connected to the ATtiny was baud setting was less than 115200.
  2. Make sure your fuses are set correctly. Especially, SELFPRGEN on the ATtiny, since it doesn’t come from the factory set.

Uploading an Arduino Sketch Wirelessly

Ok, if you were able to get the bootloader to reply wirelessly it’s time to test the whole setup. Open your Arduino and make sure you have install support for the ATtiny85,

Then, in your Arduino IDE select,

  • Board: ATtiny
  • Processor: ATtiny85
  • Clock: 8mhz (internal)

Add this test sketch,

void setup() {
  // put your setup code here, to run once:
  for(int i = 0; i < 9; i++){
    pinMode(i, OUTPUT);
  }
}

void loop() {
  // put your main code here, to run repeatedly:
  int pin = 0;
  for(int i = 0; i < 9; i++){
    digitalWrite(i, HIGH);
  }
  delay(500);
  for(int i = 0; i < 9; i++){
    digitalWrite(i, LOW);
  }
  delay(500);
}

Still in the Arduino IDE go to Sketch--->Export compiled Binary. Save the hex file to your TSB Workspace. Open your TSB Workspace in the command prompt and type the following, replacing the COM port # with COM port you have the USB-to-UART on and replace the file name with the name of your newly compiled hex file.

C:\TSB_Workspace\tsb com4:9600 fw name_of_sketch.hex

Hit the RESET button on your ATtiny85 and then hit enter on your PC. If all goes as planned the command line will change to “Reading” and “Writing” appropriately. When the file has been uploaded, reset your ATtiny85. After a few seconds each pin on the ATtiny85 should go HIGH for half a second and then go LOW for half a second. If you don’t have an LED or MM, open your serial terminal again, connect to the COM port with your wireless setup, your serial terminal should receive the character, “0x00” every half a second.

Other baud rates work. But I found anything over 38400 to be unstable.

That’s it. Let me know what questions you have.

The future

Now there is a way to upload hex files wirelessly to a large array of chips, I plan to try a few things,

  1. Write an uploader in C# which could handle controlling a PIN on the HM-1X remotely which would pull the ATtiny85’s (or other chip) reset line low. This would allow me to wirelessly set the chip into bootloader mode.
Lab Controller v05-09

Revising Board

This is an extension of previous work. I had finished a LED driver for the lab, hooked it up, and found it was a fire hazard. For the amount of lumen I wanted out of them I was having to set the current resistor to .47ohm. This was pushing nearly 2amps of current through the little FQP40N06L. The LEDs were bright, but immediately the TO-220 became too hot to touch. Two choices, either redesign or use less current, resulting in dimmer LEDs. Easy choice, redesign.

The first thing I realized was I need a heat-sink. Ironically, I had gone with TO-220s, a through-hole package, because I felt they would do better handling the heat. Ended up using the BS103AL, which is in an TO-263 package. This is an SMD package that lies on its belly exposing its back for heatsink placement.

This heatsink looked beefy enough and had the correct dimensions (5CM).

The notch on the heatsink will lie against the array of TO-263s, hopefully, drawing all excessive heat. However, the contingency is to place a fan on the back of the heatsink.

There is also an ESP8266 on the board. I decided it was a better option for controlling the LEDs, since they wouldn’t be used outside the house and would always be connected to mains. Of course, I’ve never turned on an ESP8266, so I’m hoping I strung it correctly. It does have level conversion for TX, RX, and RESET lines.

I have also added a CH340G for USB-to-UART. The CH340G SOIC chips were ordered awhile back, but before I put them into this board I threw it on an ATTiny84 breakout and tested it. I didn’t hold much hope for it, but it worked like a charm. Huh.

These little chips only cost me like $.65

CH340G $5 / 10 = .50

12mhz Crystal 1.42 / 01 = .14

The last piece of interest added to this board was a DS18B20. This is a one wire temperature probe, which I plan to thermal-paste on the heatsink as an auto-shutdown measure. Or perhaps, to reduce the amount of time a fan makes noise by kicking it on-and-off.

The design files can be found,

Lab LED Controller v09

Jazzy, Jekyll, and Swift 2.1

I wanted to take a a moment and write out how I plan to document future Swift projectss.

Step One: Install

I found Jazzy. It’s a command line utility for documenting Xcode projectss. Nifty thing is, it is one of the few which works with Swift 2+. Anyway, it is pretty painless to get up and going.

The one catch I found was Swift is changing versions often, so you may have to wait a bit for the developers to catch up. However, when the updates are released it is pretty easy to get things working again, simply run, sudo gem update in the terminal.

Step Two: Running

To run Jazzy you simply open a terminal window on your Mac, navigate to the top folder of your Xcode projects, and run jazzy. You should get something like the following,

Running xcodebuild
Parsing ViewController.swift (1/3)
Parsing bleTableViewController.swift (2/3)
Parsing AppDelegate.swift (3/3)
building site
jam out ♪♫ to your fresh new docs in `docs`

One super important note here. By default Jazzy only documents public methods. Therefore, you must pass Jazzy the flag

jazzy --min-acl internal private

This is the only way you will get everything. If not, you will end up with an empty projects, most likely. Had to find this out the hard way. Reference to the solution.

If jazzy parsed everything correctly you will have a docs folder in your projects folder. This docs folder is a pseudo-website build.

Step Three: Push to Pages

To get your documentation online, copy the docs folder to your an appropriate directory in your Jekyll site map. Commit and push. Now your projects’s documentation is apparent of the global singleton known as human knowledge. To get a link to the index of your documentation add the following,

[Test](director_you_chose_to_put_docs_folder/docs/index.html)

Here’s an example: behavioralBluetooth Docs

Step Four: Document your projects

I wont rehash Jazzy instructions. In short, you can put Markdown in your comments within the code and the parser will pick up the comments and associate them with the methods etc they are close.

Jazzy Instructions

Addendum

Apparently excluding files from the documentation process is a little tricky.

jazzy  --exclude /Users/Ladvien/Desktop/behavioralBluetooth/behavioralBluetooth/AppDelegate.swift,/Users/Ladvien/Desktop/behavioralBluetooth/deviceState.swift

It should look like above, “–exclude” (not the double dash) followed by the absolute path of the file to be excluded. Then a comma (“,”), no space, and then the absolute path of the second file you wish to exclude. It’s pretty easy to make this into a script by doing the following.

1. From the terminal type: nano my_jazzy_script
2. Paste the finished command, such as the one listed above.
3. "Write-Out" the changes.
4. Exit nano.
5. At the terminal type: chmod +x my_jazzy_script (this makes the file executable).
6. To run the script type: ./my_jazzy_script
HM-1X Aid

Overview

Well, I’ve had the urge to hack. It’s been strong for awhile now, sadly, with a more than fullt-time job and Bek in graduate school, I’ve just had no time. Until now! The new job I have (HMIS Database Manager) has actual vacation time. I’ve had almost two weeks off (combined with the Christmas holiday). The first few days were obviously spent working…But! After turning my phone and email I was able to…catch up on family time. Sigh. Then, clean house. Then, get bored. But with a few days left I actually got some hacking in.

I downloaded Visual Studio Express on my work computer a few months ago. (Shh. Don’t tell the boss.) But I’ve not had time to write a single line of code. This holiday was a good time to learn C#!

Two weeks later I had this monster,

It is meant to be a GUI for the HM-10, HM-11, and HM-15 modules. The highlights,

HM-1X Aid Download

The source can be found,

HM-1X Aid Source

  1. It uses threads to prevent any “Sleeping.” Keeps the UI healthy.
  2. IO.SerialPorts should allow a lot of USB-to-UART chips to work.
  3. Basic Terminal App features (view as ASCII, HEC, Decimal, etc.) like RealTerm and the others. BUT! With one feature I’ve longed for in a terminal app for so damn long. The ability to save your settings on exit. No more selecting 9600 baud for the billionth time.
  4. I’ve put a lot of command validity checks in the system. For example, if you were to type “AT+CON0123S6789012” Would not be a valid command normally, but terminal will convert the “S” to “F.”
  5. I have also imbued it with a bit my understanding of the HM-1X datasheets. This is probably the greatest selling point of the program, sadly.
  6. C# is my new favorite. Don’t judge me :P.

I thought I would take some time to go into the code involved in the little terminal, not for posterity, merely for my own reference.

Quick reminder, for anyone unfamiliar with my posts: I am not a profesionnal. These writings are not great. They are simply my journal towards understanding what the hell I’m doing

Object Oriented Programming

I have not posted as much lately. It is a combination of losing LMR and not having time since Bek started school. But I have definitely been writing code. The focus has been on learning OOP design. This this C# program was probably my first real object-oriented program. But I have also been writing in Swift for iOS, which is an OOP language as well.

Arlight, so what’s the difference between OOP and the other thing? And why learn OOP? I thought robots used microcontollers which are much too small to handle OOP? Well, I’m learning every robot builder is already an object oriented programmer.

Difference between OOP and Procedural programming

I wont butcher others’ explanations by rephrasing them. Instead, I’m going to list what helped me understand.

  1. Object-Oriented programming (Wikipedia)
  2. Object-Oriented programming (video)
  3. Procedural Programming (video)
  4. Derek Banas’ Design Patterns Series (examples in Java, but it helped me the most. Got to see OOP in action.)

I believe every roboticist is both an object oriented programmer and a procedural programmer. They create objects with specific functions (PCBs, STLs, etc.), holding on to the plans so copies can be made. They instantiate those objects (print the STL, send the PCB file to OSHPark, etc). Each of these objects created usually has a specific purpose. The design of the object, a motor-controller for instance, is often only accessible by a specific input such as UART connection. Its outputs are controlled by how the inputs are digested by the motor-controller itself. The robot-builder may decide to add an accelerometer to the motor-controller by copying the design files and adding the needed accelerometer circuit (inheritance). And so forth.

It seems like a lot of the the concepts are supported by this metaphor,

  1. Abstraction
  2. Encapsulation
  3. Polymorhphism
  4. Inheritance

Objects are great. Especially when they are walking, talking, grasping robotic sort of objects. However, each roboticist must line the insides of objects with procedures that move data through in a predictable manner. This means, at some granularity, objects are filled with small runs of procedural programming. Ultimately, it takes both for roboticists, object oriented programming and procedural programming. And I argue, whether aware or not, the roboticist practices both continuously.

Moving away from the hippy-dippy stuff; for my personal development as a robot builder I will be taking time to learn both, regardless of my possibly metaphor of convenience, as they both appear as roots of computational-thinking

In application, I want to know procedural programming to be effective. Microcontrollers often have small memory sets and the code needs to move from input to output with little overhead (hmm, procedural programming is a linear style and a line is the shortest distance between two points, there’s gotta be something there). But I want to know how to connect my robot to large systems, such as a Raspberry Pi, PC, or the whooooole Internet. To do this effectively I need to be able to pass data between procedural and object based programs.

Avoiding Sleep

My program is walking between the microcontroller world and the big-boy-PC world. As I stated above, at some point the HM-1X module would need to pass its data to the PC. Here in lies a dilemma best explained by a picture,

For the HM-1X Aid the data is passed through the Serial connection. Of course, as I stated above, I am using the Systems.IO.Ports.SerialPorts framework to handle the incoming serial data. A nifty little aspect of IO.Ports is it actually has the DataReceivedEvent on a separate thread (more on threads in a moment). This event is triggered by an RX interrupt on whatever USB-to-UART chip, which allows data to be handled as it is coming in.

Now, I mentioned methods for handling data probably go from procedural to object-oriented when moving upstream from a microcontroller to a PC. A USB-to-UART bridge is a perfect example. Receiving UART data for a microntroller looks like this,

int incomingByte = 0;   // for incoming serial data

void setup() {
        Serial.begin(9600);     // opens serial port, sets data rate to 9600 bps
}

void loop() {
        // send data only when you receive data:
        if (Serial.available() > 0) {
                // read the incoming byte:
                incomingByte = Serial.read();
                // say what you got:
                Serial.print("I received: ");
                Serial.println(incomingByte, DEC);
        }
}

Here, the microcontroller is looping over a if-statement to see if there is any data available in the RX buffer. Whenever the loop() finds there are data available, then it will run through some procedures on handling those data. This method works OK, your microcontroller’s program is only dealing with serial data. But what happens if is supposed to handle other tasks and your microcontroller has a never-ending stream of data? Whatever code is after the if(Serial.available() > 0) will not execute, since the available serial data will never be less than 0. This is referred to as using a “blocking” serial data method. Not sure how this term was derived, but I’m guessing “blocking” comes from how the method prevents the program from doing anything else

Hmm, wouldn’t be better to handle serial data “immediately” when it comes in? That’s where interrupts come in.

The Serial.onReceive() is an interrupt vector which fires every time the serial data is received. The interrupt vector calls a method which copies the data received from the serial buffer into the string_buffer.

void MyFunction(){
   int i;
   int length = Serial.available();
   int string_buffer[32];   

   //copy data out of the receive buffer
   for(i = 0; i < length; i++){
      string_buffer[i] = Serial.read();
   }

   //run a string compare function, or otherwise parse the received data
   if(MySpecialStingCompare(string_buffer,"Hello Arduino")){
      Serial.println("Hello World");
   }
}

void setup(){
   Serial.begin(9600);
   Serial.onReceive(MyFunction);
}

void loop(){
   //do nothing
}

This is a non-blocking method of handling serial data. It takes advantage of a hardware level peripheral on the Atmel chips known as an interrupt vector. This particular interrupt is fired any time the RX pin receives a series of LOWs which resemble incoming data.

This method has the advantage of freeing the microcontroller to do other things in the main loop and handle data only when new data is received. This saves program from having to make a comparison every clock cycle. Also, and more importantly, it allows the microcontroller to immediately update data important to the purpose of the main process; this is critical in processes which are time sensitive, such as remote control on a quadcopter.

For example, if we wrote a radio controller for our quadcopter using a Bluetooth device which talks to an Arduino Pro Mini. If we used the blocking method the Arduino receives any data from the radio controller, like, oh I don’t know, “Don’t run into that tree!” the main process on the Arduino would not have this information until it gets back to the Serial.available() > 0. Not cool if milliseconds matter.

However, if you were to write the same radio controller using non-blocking, interrupt based serial communication, then whenever you send the signal to the Bluetooth device, and that device sends it serially to the Arduino, the Arduino will basically bookmark its place in the main process and handle any data regarding its immediate crash.

Another example, what happens if your Arduino has an LCD which is meant to display the output of a temperature sensor. Yet, the temperature sensor and display are a small portion of what the Arduino is doing. If the temperature changes using the blocking methods, then the LCD will not be updated until the Arduino finishes whatever tasks and makes it back around to the if(Serial.available() > 0). This will make your LCD’s responsiveness be clunky.

Contrast this with the non-blocking method (see what I did there?). Setting up an interrupt on the temperature sensor to update the LCD whenever the temperature changes will make LCD appear responsive to temperature changes. This is how a 3D Printer handles the thousands of tasks it must complete and still keep its LCD responsive.

Good stuff.

Alright, so that’s how a microcontroller handles things–even with interrupts it’s still processing tasks one at a time. We can avoid the appearance of slowing the microcontroller with processing intensive tasks, like waiting on serial data to be received, but ultimately, the microcontroller is handling the tasks one at a time. So what does this have to do with my C# program?

Let’s take a look at C#’s version of ‘Serial.onReceive()’

string InputData = "";

// Read Data.
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
    // Gets incoming data from open port and passes it to a handler.
    InputData = ComPort.ReadExisting();
    data = "";
    data = InputData;
}

This is probably the simplest version of a DataReceivedHandler() using C#. In short, it fires whenever data is received; so it’s non-blocking. The method, as I have it written, simply grabs the data from the interrupt buffer using ComPort.ReadExisting() and shoves it into the inputData. Pretty simple, right? Being candid, I believe it is one reason so many poo-poo using IO.Ports.SerialPort framework. But how is IO.Ports.SerialPorts different than the Arduino HAL Serial.onReceive()? Hmm, perhaps I should have used a more credible comparison.

But coming back to the complex command. What if a computer sends a command to the microcontroller and expects a response? It’s going to take some time for the microcontroller to reply. In the meantime, what does the PC do? It could run off to do other tasks and wait for the onReceive to fire. But, what if one of those tasks requires some information from microcontroller. In short, the microcontroller is holding up the show and little can be done but wait.

We know the PC is going to need to wait. Coming back to the blocking and non-blocking methods we looked at on microntroller, the only option really available in C# is the non-blocking, which is good because it’s our favorite. But is it really enough?

If our PC program is serial-data centric, meaning the PC’s processes are dependent on the microcontrollers data and vice-versa, then simply using the non-blocking helps us little. The PC could move from waiting on serial data to painting a label on the UI, but what if the text in that label is meant to be data from the microcontroller? Regardless of how we look at at it, it seems like it would be best for the sake of our program to throttle the PC to the microcontroller.

But exactly how much slower would our program go?

Let’s say you have the following:

Device Speed
Arduino Uno (Atmega328P) 16mhz
PC 2.2ghz
UART-to-USB 9600bps

Let’s find the common denominator and compare.

Arduino:

16mhz = 16 * 1,000,000 = 16,000,000
1 to 2 clock cycles for each instruction
1 to 2 / 16,000,000 = 62.5 to 125 nano-seconds  
(Who said Arduinos were slow? Pfft)

PC:

2.2ghz = 2.2 * 11,000,000,000 = 2,200,000,000
1 to 2 clock cycles for each instruction
1 to 2 / 2,200,000,000 = .45456 to .90900 nano-seconds
(Oh, I guess it's slow to the PC.)

UART-to-USB:

bytes x bits_per_character / bits_per_second
1 byte x 10 / 9600
10 / 9600 = 10416666.66 nano-seconds (~10 milliseconds)

Remember, this is for one byte, so if we send the string, “Mario, your princess is in another castle” (41 x chars) it will take approximately half a second (41 x 10 = 410 milliseconds = ~0.5 second), which will definitely be noticeable if it is meant to be displayed. Hmm, I guess we identified the hold up, eh? This means even if we were limited to the Arduino speed we would probably still get a smooth UI–without it appearing clunky. But, limited to the UART-to-USB; well, crap. This affirms my speculation, we will need to throttle the PC, the UI, the microcontroller, pretty much to the whole system to be respective of the sluggishness of the UART-to-USB.

Alright, if I’ve sold you on the program we are ready to ask, “What’s the best way to throttle the program?” Let me jump how I did this in C#.

The main difference between C# and Arduino’s data receive methods is the C# method takes place on a separate thread. Now days most PCs have multiple cores and in object oriented programming these are harnessed through threading. Most microcontrollers have one core (yes, yes, except the Parrallax), so threading is not common on a microcontroller. Now, I’m going to dare to oversimplify what little understanding I have regarding threads. Since I came from the hardware side the way I think of threading is having two Arduinos connected by I2C. One of the Arduinos is the master and the other the slave. Whenever the master Arduino gets data from the USB-to-UART there is code on the master which sends half the data to the slave Arduino via I2C, with some instructions it should do some particular tasks with the data and send the results back to the master Arduino. While the slave works on its half of the data, the master is working on the other half. If the slave gets done first (there is nothing dictating which order they finish in; they are asynchronous) the master has an interrupt on the I2C, it sees the slave is done, and tells him to wait to send its results. After the master finishes, it sends a request for the completed data from the slave. Lastly, if the master finishes first, then it waits with a dirty-look only 8-bit ICs can give while the slave finishes its crunching. Ultimately, when all the data is crunched the main processor does something with it. Each Arduino here would be a processor and the tasks running on them would be a thread.

Inside the PC we have something similar going on, but instead of two Arduninos you would have two processors on the same die.

I like to think of a thread as a separate process within our system. Of course, we can’t call the second process, “main process.” We’ve already got one of those. And computers don’t like ambiguity. Instead, let’s get creative and call the second process something wild, fun, and bizarre! Like…“second process.”

Let me to try and explain how this is different than the Arduino HAL. In C# the second process is pretty much like the main process. With one grand honking exception: The user interface (UI) runs on the main process and cannot be updated by any other process. This makes perfect sense; you wouldn’t want half a button to show on your UI, right? Instead, a protocol saving data in a space both processes can access it and a flag to look in the shared space when updated. This is like the old snail-mail mailbox where the flag is raised when you want the post-person to look for an epistel.

Bringing it back to my code. The HM-1X’s serial DataReceivedEvent is on one process and my UI is on another. This means, when my program gets data serially then it puts that data in the shared space and lets the main process know data has been received.

Those of you who are probably sharper than me will notice an issue similar to the Arduino and its LCD. If the data coming in and the UI are working out of sync what happens if a user does something like continually hit the Send on a command without waiting for a serial response to be received. The best case scenario is we got an “OK” for every time the command was sent. However, if it is a more complicated command which requires a back-and-forth between the microcontroller and the PC, well, big problems. It would be like a sloth and a rabbit trying to have a conversation. Those of you from the Arduino world know the common (however, I’ll argue poor) answer to this dilemma: delay().

The delay() in the Arduino basically tells the microcontroller to do nothing for however long you tell it. After waiting the Arduino can then check to see if there is an answer waiting for it. There are two main reasons this isn’t diserable. But let’s take a look at this delay setup in C#.

//Write Data
public void WriteData(string dataToWrite)
{
  ComPort.Write(dataToWrite);
  *System.Threading.Thread.Sleep(5000);*
}

The above code will write data to the serialport and will sleep for 5 seconds after. This System.Threading.Thread.Sleep() call will actually puts the main thread to sleep. This means all of the UI will become non-responsive and anything which might happen on the main thread will be blocked. This is very similar to our first Arduino code set, but instead of receiving data, we are writing it.

The intention of this solution is to send a command to the UART-to-USB and wait for a response. A couple of problems,

  1. The main thread is shut down while waiting.
  2. Response time must be predetermined.

Now, the response time can be taken care of with better code handling it. However, the “frozen” UI posed an issue. I tried to keep it pretty simple by removing the System.Threading.Thread.Sleep().

//Write Data
public void WriteData(string dataToWrite)
{
  ComPort.Write(dataToWrite);
  DisableUI();
}

With this code the WriteMethod() is called all most of the non-critical UI elements are disabled. This gives the user the impression he or she needs to wait, without making the program appear frozen. This worked great. Not only was my RX method interrupt driven, it was on a whole different thread. There were no worries about losing important data received from the USB-to-UART. Oh, but wait, the UI never was re-enabled. Hmm.

No problem. I added a method to our DataReceivedHandler() to re-enable the UI

string InputData = "";

// Read Data.
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
    // Gets incoming data from open port and passes it to a handler.
    InputData = ComPort.ReadExisting();
    data = "";
    data = InputData;
    enableUI();
}

This worked great! Oh, but wait, if there was a problem and a response was never received then the UI was never re-enabled. No worries, let’s add a timeout feature.

//Write Data
public void WriteData(string dataToWrite)
{
  ComPort.Write(dataToWrite);
  DisableUI();
  setResponseTimeout(500);
}

// Read Data.
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
    // Gets incoming data from open port and passes it to a handler.
    InputData = ComPort.ReadExisting();
    data = "";
    data = InputData;
    enableUI();
    // Let's disable the timer since we didn't use it.
    HM1Xtimer.Enabled = false;
}


// The consumer interface for the response timer.
public void setResponseTimeout(int responseTime)
{
    responseTimeout = responseTime;
}

// Creates the response timers and attaches the elapse method.
private void HM1XCallbackSetTimer(int milliseconds)
{
    // Create a timer
    HM1Xtimer = new System.Timers.Timer(milliseconds);
    // Hook up the Elapsed event for the timer.
    HM1Xtimer.Elapsed += hm1xCommandTimedCallback;
    HM1Xtimer.AutoReset = false;
    HM1Xtimer.Enabled = true;
}

// This event is fired if the response timer elapses.
private void hm1xCommandTimedCallback(Object source, EventArgs e)
{
    if (data == "")
    {
        waitingOn = hm1xConstants.hm1xEnumCommands.ERROR;
    }
}

Yay! That code is darn clever, right? Let’s compile, run it, and celeb…son-of-a-B! It wouldn’t compile.

The problem is with the enableUI() call in the DataReceivedHandler() method. It seems the DataReceivedHandler() is actually taking place on a separate thread from the main thread, and the main thread is where the UI is being maintained. This is where the good-ole-Ghostbusters adage is important to recall: Don’t cross the streams! EVER! Staying away from explaining what I don’t understand, I’ll simply say: Don’t cross thread. One thread should not be updating what another thread is working on. Instead, information from one thread should be set down and the other thread notified it is ready.

These metaphors are nice and all, but how do we implement a thread friendly solution?

//Write Data
public void WriteData(string dataToWrite)
{
  ComPort.Write(dataToWrite);
  DisableUI();
  setResponseTimeout(500);
}

// Read Data.
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
    // Gets incoming data from open port and passes it to a handler.
    InputData = ComPort.ReadExisting();
    data = "";
    data = InputData;
    enableUI();
    // Let's disable the timer since we didn't use it.
    HM1Xtimer.Enabled = false;

    // Pass data to main thread.
    gotData(sender, data)
}

....

// RX event handler triggered by SerialPort.  Hands off data quick.  
// If you try to update UI from this method, threads tangel.
public void gotData(object sender, string data)
{
    // Incoming data is on another thread UI cannot be updated without crashing.
    this.BeginInvoke(new SetTextCallback(SetText), new object[] { data });
}

// This method happens on main thread.
public void(string text){
  txbMainDisplay.Text = text;
}

This is pretty complex and I poorly understand it. In fact, I wrote this whole article with the hope it would help me understand this part. Here’s what I think is going on:

We create an event which will fire every time the USB-to-UART, DataReceivedHandler() in this method there is a call to gotData(). In the gotData() call we use the BeginInvoke method. The BeginInvoke then executes SetText() method on the main thread. We know ‘SetText’ is being called from the main thread because of the word this in the command. This is a place holders for the object of origination. It looks complicated, but really, the thread controlling the UART-to-USB is simply calling a method on the main thread whenever it has received data, and passing it the data it received.

And that’s it. Using this method we can enable and disable the UI every time data is sent or received.

A few more notes,

  1. This method doesn’t need to be used for disabling the UI. The WriteData() is actually executed on the main thread. It is the DataReceivedEvent() which is executed on a different thread.
  2. This process gets a little more complicated when you are dealing with multiple objects, which is what I did. In my code SerialPortsExtended object handles all the data receiving and sending of data, so delegates are used to pass data back-and-forth between threads and objects.

That’s about it. Let me know what questions I can try to answer.