This toolchain is amazing. Really, if you are wanting to break away from Arduino / AVR, into the ARM chips, Bdk6’s toolchain for the LPC1114 is the way to go.
The Valdez Mutant v04
The chip has ROM boot loader. This allows you to program the chip right out of the box. The programming is done over the traditional serial line. Most ARM chips require a JTAG programmer, which are usually a $50 investment. This leads into a few of my design goals.
A-2. Arduino Pro Mini (APM) FTDI programmer to program the LPC1114
After doing a bit of AVR programming I toyed with the idea of getting into the Atmel ARM chips. One barrier to entry is cost, and now that we are down to one income this is a Hannibal to Rome grade barrier. Not only were most of the chips in the $6-20 range, they required a JTAG connector to program. Ultimately, price kept me from building a board around an Atmel ARM chip.
But then Mr. Bdk6 introduced me to the LPC1114. Not only was the chip sub $3 in single quantities (cheaper than the Atmega328P), but it was also programmable with a typical serial-USB interface. I figured, if it was programmable by serial then I could program it with my Arduino Pro Mini FTDI Breakout, which I bought from SparkFun long ago. I did this selfishly, but I assumed a lot of Arduino roboticists here have also switched to the APM as their go to board. I further assumed most would probably have a APM FTDI connector. I took this into account because my goal was to reduce as many barriers in switching from Arduino to the LPC1114, short of writing simple and opaque support libraries.
I’m going to take a brief moment and explain the LPC1114’s ISP ROM. The LPC1114 has a built in bootloader, which resides in a ROM block on the chip. When the chip is provided power, either on initial or reset, it runs this bootloader. The bootloader polls PIN 1 on PORT 0 (PIO0_1), if this pin is high or floating, then the bootloader executes whatever is in the program memory blocks. If PIO0_1 is low, then the LPC1114 enters in-system programming mode.
When I discovered this, I got excited. Why not use the DTR/CTS pins to control the ISP? I added it to my design goals.
A few problems:
1. The LPC1114 operates on 3.3v. And don’t let your “3.3V” FTDI breakout fool you. They still spit out 5V on for VCC, RX, and TX, at least until you jumper the solder-jumper on the underside. No sweat, I’ll add a logic-level translator.
2. There is no existing LPC1114 programming software that controls DTR/CTS.FlashMagic and lpc21isp both use DTR/RTS, while the APM FTDI breakout I have uses DTR/CTS. Stupid dung-beetles in the ointment. I was committed to the idea of using the APM FTDI connector as a “no-modification” way to program the LPC. Thus my toils began.
I started by trying to change the source of the lpc21isp. I was successful in manipulating the source, but the lpc21isp relies on Windows communication protocol drivers, which don’t allow for the bit level control of the CTS pin. Damnit.
I started re-rolling my own bootloader using FTDI drivers, which do allow for bit level control of all pins (FTDI Bitbanging). Sadly, I got distracted by writing a iPhone app for the HM-10. By the time I finished the app, Bdk6, who heavily guided me on how to re-roll the programmer, stated he was writing one and would attempt including the features I requested. I figure, “I think this is one time being lazy is in the best interest of everyone.” I let Bdk6 write the programmer. :)
A-3. _Almost _the same size as the Arduino Pro Mini, but with Mounting holes.
I love the Arduino Pro Mini (APM) for robot building. It is small, powerful, robust, it’s just good stuff all around. When I decided to build an LPC board I wanted it to copy it in design.
Here are the features I pulled:
1. All components are on one side (except for the HM-11). This allows for easy reflow.
2. Small. The Valdez Mutant is the same dimensions as the Arduino Pro Mini, except for the “diving board” area where the HM-11 sits. APM is 18x33mm and the Valdez Mutant is 18x46.97mm
1. I didn’t put a reset switch. I was banking on the BLE being able to reset the HM-11 serially (I’ll get to that in a bit).
2. A power LED. I decided the RGB LED blinking for the HM-11 could double as a power-led, since the power-rail is the same for the HM-11 and the LPC1114
I added one feature that I’ve always felt the APM was lacking: Mounting Holes. Some time ago I realized as I continued challenging myself to make smaller and smaller PCB solutions, there gets a point where the board is too small to easily work with. The connecting wires hold it in the air, or pull it off where you set it. I decided I’d add 3mm mounting holes to hold my board in place.
A-4. Wireless Programming Over BLE.
I’ve always dreamed of hooking up a Bluetooth module to an Arduino and uploading sketches wirelessly. When I discovered the HM-10 I thought I had a real chance (I’ve not completely given up on the idea), but it took editing the Arduino IDE source. I was able to tweak and compile it, but if anyone who has been through the Arduino IDE source will tell you, it’s a friggin mess. But when I went over the design of the LPC programmer interface, I realized the process of flipping bits on the ISP SELECT and RESET lines with the FTDI could be done remotely by the HM-10, using the PIO pins. Hmm. Light bulb.
I therefore set out to design a board that would allow for wireless uploading of programs.
Instead of using my traditional go-to HM-10, I decided to switch it up and attempt using the HM-11.
The HM-11 is pretty much the same board as the HM-11, but instead having the 8 or so IO pins, it only has 2. Perfect. One for RESET and one for SELECT.
I thought the HM-11 would allow me to stay consistent with design goal #3: Itty-Bitty.
In theory, this is how the wireless uploading would work.
HM-11-A sends “AT+PIO30”
The HM-11-B PIO3 will go low, which sets the LPC1114 ISP MODE to LOW.
HM-11-**A **sends “AT+PIO20”
Then, the HM-11-B PIO2 goes LOW for ~5uS. This will reset the LPC.
As the LPC comes back up it checks the ISP MODE pin and sees it LOW.
HM-11-**A **sends “AT+PIO31” waits ~100mS then sends “AT+PIO21”
The HM-11-B PIO3 and PIO2 will go HIGH.
The LPC enters ISP mode.
The HM-11 PIO2 & PIO3 go HIGH.
The program is uploaded to the LPC.
HM-11-**A **sends “AT+PIO20”
HM-11-B PIO2 goes LOW, resetting the LPC.
HM-11-**A **sends “AT+PIO21”
HM-11-**B **PIO2 goes HIGH and the LPC runs the uploaded program.
Testing this board was a bit of a bitch. The first version (v02) I printed had several major flaws:
Mistakes on 1st iteration:
The RX/TX lines were flipped (I swear, I never get that right).
The CONN pin on the HM-11 was wrong.
I routed the CTS pin to pin PIO02, which is _not the reset pin.
There was a N-Chan flipping for the HM-11 to flip the LPC power. I got rid of that and simply ran a line to the reset (duh).
I quickly corrected these problems and sent the board off again. When the 2nd Iteration came in I wasn’t able to test it. No matter what I did I couldn’t get it to go into ISP mode. I got pretty harsh on myself, blaming my “crappy soldering skills and dellusions of ability.” Then it hit me, I had added 10uF and those take a bit to discharge. I threw the multi-meter on it and sure enough, when I pulled the power from the LPC, then reapplied it (I was using this method instead of the reset line) it took a good 30 seconds for the voltage to drop near nominal. I quickly strung up a momentary switch on the reset line, first time I hit the button it went right into ISP mode. Son-of-a-badger!
Therefore, I consider the 2nd iteration a hardware success.
But there was a big let down. I tried both FlashMagic and lpc21isp to get them to upload across the BLE connection, but they both timed out. Ugh. I guess no wireless download?
FTDI pinout – Working – 50% tested – (works to provide power and RX/TX work, ability to reset and select mode not yet tested. This will require customer software).
5v/3.3v RX/TX converter – 100% tested – Working
DPDT Switch to select HM-11 or USB – 100% tested – Working
Crystal – not yet tested 0%
HM-11 – RX/TX – 100% tested – Working
RGB TX/RX/CONN – 33% tested – CONN Working
LPC reseting HM-11 – not yet tested 0%
HM-11 controlling RESET and ISP MODE – not yet tested 0%
Board Tested and Working: 48%
B-2. Support and Design Files
I’m a hack. I wouldn’t even be hacking with LPC1114 if it weren’t for the support tools put together by Mr. Bdk6.
Alright, so now what? Um, let’s build a robot with it. To do this, I’m going to design a motor PCB with the DRV8837. And I’m hoping that Mr. Bdk6 doesn’t mind adding the FTDI reset features and the HM-11 upload features. If he doesn’t have time, then I’ll probably pick back up my attempt to write my own bootloader.
I did notice a few problems. First, I didn’t allow for a VIN pin. This means I’m going to have jumper between a “shield” board and the Mutant. Also, I’m worried about fitting two H-bridges on a PCB as small as the Mutant, the DRV8837 is very small, but the traces to it take a lot of real-estate.
Well, that’s it.
A huge thanks to Mr. Bdk6. These tools are amazing; finally escaping Arduino!
(This node will probably float a bit, have lots of work to do on it. My apologies.)
I’d been wanting to create a bridge between Arduino and iOS for awhile. Not going to lie, not a huge fan of iOS devices, but since my wife won an iPad Mini I’ve begrudgingly accepted they fill a need. Still, my hacking has orbited robotics and any device I can’t connect to a robot frustrate me. Well, a year ago I realized an iPad Mini would connect to an HM-10, and therefore, robot.
Sadly, the app used to connect to the HM-10 was LightBlue, an app with little versatility. However, it allowed me to confirm everything was in place to the connect the iPad Mini and a robot. Of course, I wasn’t willing to pay several hundreds of dollars at the chance I could develop an app. Well, the idea got filed under “NSF.”
But, two months ago I was contacted by Simon Riley, the CEO of Carduino. He asked why I had stopped short of developing an iOS app to interface with the HM-10 BLE Serial modules. My response was short: Lack of funds. I explained to develop in iOS (legally, and therefore weary and worry free) you need an iOS developer’s license and a Mac to develop from; I hadn’t money for either. Simon responded the next day, “Maybe we can help with that.”
Long story short, Carduino donated to the cause and I used my robot allowance (you married guys understand) to purchase the rest. So, what did I get?
Mac Mid 2009
Price ended at $469.99. I spent a little more than I should, but since Carduino had added to the kitty I was worried about getting something I’d be unable to run Xcode. Therefore, I spent a little extra in hopes to get a machine that would allow me to write code efficiently.
I have to take a moment and remind people, I wear a white hat. Dear Amy2865, before you sell a laptop, be sure to log out of your eBay account. Also, Jared Kusma, I’m liking your laptop, but I _did _clean the keyboard thoroughly before using it. And the spots on the screen.
Alright, enough of the teasing. Moving on.
I deal with clinical delusions. But, I’m learning to force them to serve me. I realize I’ll never be as good as I feel in the throes of a delusion. Yet, I’ve allowed these words to guide me,
Believing I can do anything, may not be true. But believing it is enables me to do_ almost_ anything.
Well, when I accepted Carduino’s funds to help develop an app I might have been delusional. I didn’t tell anyone I’d never used a Mac before, let alone wrote Objective-C. But one thing I believed, if I determine myself to do something I will. Of course, my timeframe is my own and the product might be apparently hackish, but it will get done.
Anyway, I admittedly had no idea what I was doing, so I decided to journal as I went.
This brings me to my disclaimer:
I am not a professional programmer. I do not pretend to be. With that, please feel free to point out my mistakes, inefficiencies, or ineffective code in general. Part of the reason I post articles like this is for the peer-review. But don’t expect me to apologize much for stuff I didn’t catch. Working a full-time job in a non-tech field, having a wife in graduate school, raising a four-year-old, well, these things leave me little time to program, and nearly no time for code review.
I don’t think there are mistakes in my code, I know there are. Alright, self-deprecation aside, let’s get going.
1. Setting up the Environment
First, you need a Mac and a Developer’s License. The Mac really needs to be at least 2008 or later to effectively code for the current iOS (7.1 at writing, 8.0 being in beta).
After looking over many “deals” on eBay I decided on a Mac Book Pro 2009. It seemed old enough people didn’t have an unhealthy attachment. Later than 2009, it was like people were selling their pretty daughter.
I chose the Mac Book over Mac Mini. The Mac Book came with a monitor and peripherals. Maxhirez warned me some Mac Mini’s have proprietary video out, which would force me to buy a monitor as well.
I was a a lot worried an eBay Mac would be DOA. When it finally came in, I was relieved to see it boot up. But, within an hour it overheated and crashed. Worried the crap out of me. I then realized this laptop had two video cards and the display settings were full-blast. I backed down the video settings and the temperature seemed to hold. Still a little worried. When I get the app written for Carduino I’ll probably take it apart, clean the heat-sink fins and reapply thermal paste.
You will need to apply this certificate to the apps you write to publish them–even on an ad hoc basis.
2. The App We’ll Write
This write-up describes writing an app for Bluetooth 4.0 iOS devices to enable a serial connection to an Arduino. To facilitate the serial connection on the Arduino-end a HM-10 acts as a peripheral, which in turn, interacts with the Ardunio via a serial connection.
The HM-10 operates on 3.3v and the Arduino 5v, but I created an Instructable on how to convert the HM-10 to 5v.
Before I started this projects I’d never used a Mac, never seen Xcode 5, let alone looked at Objective-C code. But, like the delusional man I am, I thought, “Well, it’s got the word ‘C’ in its name; couldn’t be that hard for me to learn.” Stupid me.
Objective-C is silly. Well, I shouldn’t say its entirety is silly; the verbosity and syntax are silly, though. The idea being everything is spelled out, nothing abbreviated, which makes the code chewy to read. Anyway, I’ll stay away from psychological rants about brevity being the essence of wit. Or how humans will psychologically gravitate towards messages easy to encode and decode.
This article isn’t going to go into much on how to write Objective-C or use Xcode, since there are already many excellent guides.
His written tutorials are free, but giving the visual component of Xcode I paid $15 for a subscription to his video tutorials. Both written and video tutorials are excellent. Learned pretty much everything I needed from him and his peers.
I would list other tutorials, but really, Ray’s covers everything you’d need to write this app–well, besides the Bluetooth part, which I’ll cover. But one surprisingly helpful video was Apple’s introduction toCoreBluetooth Framework.
The app we’re going to write is pretty simple. Really, it is. It takes the values from two Slider Controls and sends them via Bluetooth to an Ardunio. The Arduino in turn converts these values into direction and PWM values for two wheeled-motors.
Ok, open Xcode and let’s start a new projects. We are going to use a Single View projects.
The first step in creating our app will be laying out the user interface. This boils down to a few items.
View for Background Image:
3 x Labels – Steer Value, Acceleration Value, RX Data
Just download the projects as zip. Then, within the projects there is another zip titled: bleAppStartLayout.zip Simply unzip this projects and open it in xCode if you’d like to write your own code to go with the skeleton layout.
There are three parts to the code of our app.
Code to control…
The Bluetooth connection
In this article I’m only going to cover the Bluetooth code in depth. The rest is either pretty straightforward
Objective-C Bluetooth Code (and some UI):
Before we get going, it’ll help to be slightly familiar with Bluetooth 4.0’s standards and protocols. Also, iOS’ recommendations on using CoreBluetooth, Apple’s API for Bluetooth 4.0 hardware.
The big take away for us is the differences between Central and Peripheral roles.
This doesn’t mean our bot cant receive data or iOS device can’t send data, it simply defines the relationship between the devices. The role decides which device controls the connection and data flow. For the sake of this app thebot will be setup as a Peripheral and theiOS device will be the Central. This is my opinion, but it seems the BLE hardware connected to the uC or CPU with the greatest speed should take the Central role.
The header file – bleApp.h
To access the Bluetooth 4.0 functionality of compatible iOS devices, Apple provide the CoreBluetooth Framework. This framework is brought into your app code in the typical C fashion, by importing it inbleApp.h
Once the framework is imported we have access to the API methods.
Alright, I’m going to attempt explaining something I poorly understand, Objective-C Delegates.
I believe a delegate is a collection of services your code can subscribe. I think of them much like interrupts in Arduino. Each time a specific event happens a method is called. You setup the delegates you wish to subscribe at the top of yourbleApp.h:
Here we are calling on subscribing to four delegates:
The CoreBluetooth Central Manager, the CoreBluetooth Peripheral, User Interface Table View Delegate, and the User Interface Table View Data Source. Right now we are only going tofocus on the Bluetooth delegates.
Another way to think of delegates is a collection of little scout robots who report when a specific event takes place.
These delegates are a collection of little methods who will be called at specific events. For example, the CBPeripheralDelegate has the method-(void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error. This method is called whenever iOS app discovers BLE peripheral. Again, these methods areevent driven–this means something usually has to happen before the come report to your code.
Here are the major methods we will be using to control the iOS BLE hardware:
Next, we declare the properties we will need. If you know as little about Objective-C properties as I did here’s a good tutorial.
That should be all the code we need in our header file.
bleApp.m – Our Implementation
1. The UI Connection
Objective-C operates under the Modal-View-Controller design modal. We don’t have to go too deep into this design theory to be dangerous, the main thing we want to take away is UI elements are connected to our code with keywords. For UI elements we wish to change programmatically we set aIBOutlet and for UI elements we wish to generate an action we use the-(IBAction) methods.
An example of using an IBOutlet would like this:rxLabel.text = @”Got data”;
All good, now how do we make IBOutlets and IBActions? First, click on the “Tuxedo” button
Now, hold CONTROL and click on the UI element you want to create an Action or Outlet, then drag to your code between@interface and@end.
Ray Wenderlich’s tutorials explain this process well. So, I wont rehash. A couple hints though, you can type out each of the IBOutlets and IBActions, but unless the dot on the bar next to where it is written is filled in, it is not connected to an element. Also, if you hover your mouse over the little dot while in tuxedo-view, the element it is connected to will be highlighted.
Ok. So, we need to connect up all of our UI elements. I’ll simply refer back to my video on the layout. Or I suggest you use the skeleton bleApp layout, since I’ve already wired up the UI elements.
Either way, we need to end up with code that looks something like this:
Ok, let’s get our Bluetooth going. Objective-C has a method that runs once if the UI loads,-(void)viewDidLoad method.
We will add more code in this method later, but for now this will work. Here, we are simply allocating and initializing an instance of the CBCentralManager object. It has two arguments,initWithDelegate, we set this to self and the queue we set to nil. This allows us to inherit the CBDelegate from the ViewController.h. The queue being set to nil simply means we are going to allow the CentralManager to manage our data.
This method is called each time the BLE hardware on the iOS device changes state. Here, we are using it to check if the iOS’ Bluetooth hardware has been turned on.
ThecentralManagerDidUpdateState is a method called by the CoreBluetooth (CB) Central Manager Delegate whenever the BLE hardware in your device changes state. Here, it is being called when our app first begins. It will also be called each time the iOS Bluetooth is turned on or off.
The central.state property is set by the CBCentralManager Delegate. It has six states:
CBCentralManagerStateUnknown – Device can’t be read, etc.
CBCentralManagerStateResetting – Device is resetting
CBCentralManagerStateUnsupported – this device doesn’t support BLE.
CBCentralManagerStateUnauthorized – Your app isn’t authorized to use BLE
We will only be using the last two states. Our code checks if the BLE hardware is enabled; if it is not, it does nothing. Eventually, I’ll probably add an alert to notify the user, but right now, it does nothing. If the hardware is enabled, then it executes the centralManager instance method with two argumentsscanForPeripheralsWithServices: nil andoptions: nil.
In case you didn’t have time to read the BLE protocol manual, I’m going to give you a crash course. Let’s start with the service tree. The magic of Bluetooth lies in its advertisment protocol. The Central BLE device is scanning the air, while the Peripheral is advertising its information. The information advertised coordinates services the peripheral device has available.
If you have a minute, Ada has an excellent article on Generic Attribute Profile (GATT) written by Keven Townsend (I like his stuff).
Keep two things in mind, first, I’m still learning what the hell I’m talking about. Two, jnhuamao and I have a history. I’ve watched their BLE firmware develop over the years. When the first procuded the HM-10, it didn’t conform to any BLE protocols. Now, they’ve got a damn fine product. Of course, they seem to be trying to get old school Bluetooth thinking to fit BLE. For instance, they equate the “Master” role of their modules with Central role protocol. Likewise, they equate “Slave” with Peripheral role. This confuses me a little, since
For the HM-10 it looks something like this,
When iDevice scans the HM-10 it’ll report back the FFE1 characteristic, which is the characteristic address for RX/TX on the HM-10.
The centralManager didDiscoverPeripheral method executes every time a new service has been discovered. It provides several bits of information about the discovered peripheral. First, the peripheral information itself, this includes its name, UUID, etc. Further information can be pulled from the advertisementData dictionary. Lastly, which is a neat attribute of BLE, you can access the RSSI of the discovered device before ever connecting.
9:Our code set an instance variable_discoveredPeripheral to the most recent discovered peripheral.
12: Creates a string variable and sets it to the discovered peripheral’s UUID.
14: Checks to see if we got a proper UUID string in the uuid variable.
17: Here we are calling the setter method for thedevices NSMutableDictionary. We are setting the object service information from the discovered peripheral and the key is the discovered peripheral’s UUID. This is going to allow us to recall at least 6 discovered services.
- (NSMutableDictionary *)devices Sett Method
We are going to store the last six peripherals discovered.
4: We check to see if we’ve initialized the dictionary. 7: If we haven’t then we setup the dictionary with a six device slots, then, we set a slot to the last discovered device.
10: When we are done, we return the devices dictionary.
The devices method will be called many times throughout our program. Eventually, we will use the dictionary to populate a table of discovered devices.
The centralManager didConnect method executes whenever your app connects to a specific BLE device.
5:Once we’ve connected we activate the peripheral delegate methods.
8: After we have connected to a particular peripheral, we call theperipheral discoverServices method. Again, by setting thediscoverServices tonil we search for all services on our newly connected peripheral.
Here, we enumerate through all the services on the connected peripheral. This is a slow way to discover services, but it’s inclusive and easy. And since the HM-10 only has two services, and only one service active at a time, we don’t lose any time.
4: This is a fancy for-loop called enumeration. It goes through all the services listed in the(CBPeripheral *)peripheral, which is a small list on the HM-10. If it is in the peripheral role, which is default, it only has one service.
7: Here we calldiscoverCharacteristics method on each service on our connected device. Again, passing thenil argument means we want to discover all characteristics, as oppossed to a specific. Slow, but inclusive.
For each service, we enumerate each of its characteristics.
4: We go through each characteristic of each service on the connected peripheral.
7: We call thediscoverDescriptorsForCharacteristic method on each discovered characteristics.
We are accomplishing two things in this method. First, we are getting the character version of the hex values FFE0
6:The firs thing we do is convert the HM-10’s characteristics from FFE1 to character values, 255 and 225.
8:Next, we check to see if we got two characters, and they are 255 and 225
12-23: We do a quick enumeration through the services and characteristics. For each characteristic, for each service, we call the selectedPeripheral setter method. We pass thesetNotifyValue argument totrue. This automatically receives serial data. Each time serial data is received the method
We’ll write our RX method when we get to UI, since we’ll set our rxDataLabel to automatically update with incoming data.
Also, the we are setting up an automatic RX notification method. But, another way to do this is by setting thesetNotifyValue to false. Then, each time you want to get RX data you can call thedidUpdateValueForCharacteristic method manually.
This method is called whenever we want to send information to the peripheral. It has data passing argumentstr, but we wont be using it. The app we are writing automatically assemblies a data string and send it to the peripheral each time it is called. To send our data we simply must insure it is in the appropriate variable.
This app takes the values of two slider with a range of -255 to 255. We then do a little data manipulation. On the iOS device a byte takes 8 bits. Same for an unsigned character. But I found if you assign a value greater than 127 then ARC will automatically generate two-bytes for a single unsigned value. To get around this and hang on to full resolution of the Arduino, we convert the slider ranges from 255 to 125-0 or 125-1. The one is a bit set in a switch-array,controlByte. Then, when the Arduino receives the data it converts it back to full range, 255.
Regarding the direction, using the same switch array,controlByte, weset a bit low or high depending on whether the slider indicates 0 to -255 or 0 to 255. Again, when this makes it to the Arduino it is converted into direction of the motors.
Ok! Let’s step through the code.
3-6:Like before, we are enumerating through all services and characteristics on our connected peripheral.
8-9: We get the slider values, round them into an integer and load them into appropriate integer variables steeringValue and accelerationValue.
14:Setup a data variable to hold our send string.
25:We create a byte variable to act as our switch-array.
29-42:Determine direction the motors should go based on the sign of the sliders.
45-58: Decide whether we need to divide the range.
67-69:Load the processed data into data variable.
72: Create a string using the data we’ve processed, then, convert it to ASCII to be sent to the Arduino.
75:Add the “:” character, which will act as our end-of-transmission character.
78:Finally, we send the completed data string to the peripheral.
Full source code for this projects can be found here: