Bluetooth between Android and HC-05

In a previous post, https://astrospanner.wordpress.com/2016/04/13/bluetooth-enabled-lcd-driver/ I talked about the hardware side and the code on the PIC.  This post is about the android software. I wasn’t able to find a good reference on how to do this, so there was some experimentation, hence the need for a clear post like this.

Introduction

Android uses, not surprisingly, a “client” and “server” model for Bluetooth communications. This is outlined in their developer guides (http://developer.android.com/guide/topics/connectivity/bluetooth.html), but it assumes you are connecting two android devices, and so can decide which is the client and which is the server. This isn’t the case here, adn the HC-05 documentation doesn’t specify whether its a client or server. It talks about “slave” and “master”, but that doesn’t really help…

An Aside

I am not a particularly skilled Android developer. When I see examples like this

CaseInsensitiveString cis = new CaseInsensitiveString("Polish");

my brain struggles; why am I having to type “CaseInsensitiveString” twice? Isn’t the compiler meant to be sorting out type dependences like this for me?

After a while I realise that this is

  1. defining a new object called “cis” of type “CaseInsensitiveString”
  2. Assigning it to a value of “polish”

The Android developer guide has the following example

BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

It’s good that we can all type “Adapter” correctly after these examples…

What I found

The HC-05, when configured as a slave (as by default),  works as a “server” (in the Bluetooth Socket sense).

The process that Android code has to do is then straightforward

  1. Make sure Bluetooth is on
  2. Setup to talk to remote device by MAC address
  3. Create an RF Comm socket
  4. Connect the socket
  5. Get the output stream for the scoket
  6. Write bytes into the outputstream

At Point 2, you need the MAC address of the HC-05. This is discoverable by code, (I used what is reported by BT Term for this, which is a cheat), but I’ve not yet implement it.

At Point 3, you need to set a UUID. I initially thought this was just a random number, but you need to be specific; its this UUID that tells the HC-05 that you are connecting via SSP (Simple Serial Protocol). The magic ID is

00001101-0000-1000-8000-00805F9B34FB

Searching for this ID specificially shows that its in the Adnroid Bluetooth guide, which shows I didn’t read it properly…

 

Code fragment

The resultant code (with try/catch blocks removed for readability) is then. This is single threaded, blocking, and probably gives real Android developers a hernia. Hopefully its useful for someone.

String address = "98:D3:31:FD:18:B8"; // todo remove hardcoding

UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

BluetoothDevice device = BA.getRemoteDevice(address);

btSocket = device.createRfcommSocketToServiceRecord(SPP_UUID);

// connect.
while (btSocket.isConnected() == false) {
    try {
        btSocket.connect();
    } catch (IOException e) {
    }
}

// write a message
outStream = btSocket.getOutputStream();
String message = "M07Conn...";
byte[] msgBuffer = message.getBytes();

outStream.write(msgBuffer);

outStream.flush();

Conclusion

The code works, and I have a specific app on my home which will connect to the HC-05, and push things onto the screen. I then started noticing timing issues, which will have to be dealt with. But it’s now time to finalize the hardware and package it properly.

Advertisements

Bluetooth enabled LCD driver

New project!

This is a really a re-fresh of an old project. In a previous job, I had an office and lab, and it wasn’t always obvious how long I’d been gone from my office. I built a little PIC controlled system with a switch that would either display the message “astrospanner is in” or “astrospanner left xxx seconds ago”. Now, I want something where I change the message easily to say things like “astrospanner has gone home”, “astrospanner is calibrating an instrument, back in a month”. Most PIC projects have a clunky set of switches to allow for things like message adding, which requires lookup tables and is slow. Yuck. Instead, I want a wireless connection to something with a keyboard. The ideal thing would be a connection to my phone, so that limits me to internet connectivity or bluetooth. Wireless internet would be suitable (if not overkill) if I used a Raspberry PI, and had tight security, so that was rejected as I wanted to something with a PIC.

This post is going to be a description of the debugging steps of getting to a working breadboard system. Full docs (circuit diagrams) will be in a later post.

 

System diagram

The basic system diagram, before any research, is as shown:

System diagram for BT

System diagram for BlueTooth enabled LCD display

A quick google search for “bluetooth module” brings up a bunch of hobbyist suitable things, including the HC-05. Because it was hobbyist based, it seems to come in slightly different mounting versions, but all the data-sheets talk about  serial mode transmit and receive, as well as a bunch of “AT” commands for configuration.

My project box had a couple of 16×2 LCD character displays (I tend to by what I need for a project + spares, meaning the next project has a bunch of additional parts to play with already available), and I’ve got a Microchip PicKit1 programmer, so I went searching for a PIC that

  • PICkit1 compatible
  • serial port
  • Enough output pins to drive the LCD module

The LCD module is a Hitachi HD44780 compatable LCD, with the component number JHD 162A. A variety of datasheets exist explaining it exist, but I used Julyan Ilett’s guides from here:

Guide 1.pdf

and here

Guide 2.pdf

(googling “Julyan Ilett Intelligent LCDs should find them)

The LCDs have 8 (!) data lines (give them a break; they are from the era of parallel ports for printers), and 2 (important) control lines (2 are required, an additional line is required for reading data back from the LCD). A second mode of the LCD allows only half the data lines to be used, so 6 lines to be controlled from a PIC. Because I had one in the project box, I added a serial to parallel chip (74×595), which requires 3 control lines to produce 8 data lines, so the PIC required 3 + 2 lines to control the LCD (a 2nd 74×595 chip would reduce this to 3 if required; the previous version of this project used an 8pin PIC to drive two 74×595 chips to control the LCD) and 2 for the serial port. This all pushed to a 14 pin device, and the microchip website listed the 16F688 as being suitable.

After some ordering from hobbycomponents.com, I had all the bits I needed…

bt1

HC-05 module, with 1p for scle

bt2

Backside of HC-05 module. Documentation on the silkscreen for users! Awesome!

 

The HC-05 module. I really like the silkscreened interface information on the back (including voltage levels for power!). It turns out the TX output is 5V TTL/CMOS compatable, but all info recommended 3.3V only for the RX lines. Important to know if the rest of the system is running at 5V levels…

lcd1

LCD module, doing an impression of cthulhu

I had to solder the (solid core for prototyping) wires in myself, which is why there are some red and some purple lines. The purple wires are from previous experiments with the 4 bit control mode.

 

Development

Throwing everything together would not have worked; end-to-end testing is vital, but for development, splitting things into smaller, individually testable chunks makes life much easier. I split this into 4 stages

 

  1. PIC driving 74×595 driving LCD
  2. Serial port talking to PIC
  3. Serial port talking to PIC driving 74×595 driving LCD
  4. BT module talking to PIC driving 74×595 driving LCD

 

I’ll go through some pitfalls for each, and things I learnt, in the following sections

PIC driving 74×595 driving LCD

This was OK. I’d done it before, and I understood the addressing modes of the LCD. The idea is to

  1. set the data lines, corresponding to a character you want to display
  2. set the RS line high (for characters) or low (for commands)
  3. set enable high, and then low.

It’s the transition from enable high to low that the LCD picks up on, so everything else can be done slowly, quickly, by careful re-wiring…

The trick is to get everything turned on first; by default the display is OFF and the second line is OFF when the LCD is powered on. Sending the commands 0xf (blinking underline cursor) and 0x38 (8 bit data, two lines, 5×7 format) do this.

I wrote some code in C, compiled by the microchip tools, and this worked. But the sequence of unplug, reprogram, plug back in, just to change the message was tedious. Time to get the serial port working…

Serial port talking to PIC

I’ve implemented the serial port on the PIC before, so this wasn’t too bad. But previously I used a PICkit3, which allowed for in-circuit debugging, which is a definite advantage! Showing my age, my previous work had been done on a windows NT system (!), which had Hyperterminal present. Hyperterminal doesn’t exist on Windows 7. There’s a “private edition” with the same look and feel, but with a nag screen. Instead, I used RealTerm. Terrible webpage, fantastic program. Allows closing and opening of the port without reloading (which in hyperterminal, especially with a nag screen, is a pain), and allows hex output. Definitely recommended.

The voltage levels between a PCs serial port (RS232, so -12V!) are NOT the same as the serial port on a PIC (TLL). I used a TTL USB port like this one; it pretends to be a serial port (so RealTerm talks to it) and it outputs TTL voltages, keeping the PIC happy.

The “serial port” on the PIC allows for asynchronous operation, which demands your PIC code deal with interrupts. There’s also a correction required to the PIC 16F688 docs; I found that the PIC was unable to receive until I set the port to receive by setting the TRISA register correctly (the docs say this is automatic!).

The interrupt service routine, which only cares about the serial port, looks like this:

 

void interrupt general_ISR(void) {
    // interrupt service routine. 
    // only care about GPIF at the moment...

    // if interrupt raised, we should have received a character.

    // load character into data area, charrecived,
    // and increment unprocessedcharacter

    // receive

    if ((PIR1 & 0b00100000) == 0b00100000) {
        // ie RCIF has been set, because something has been received
        // not dealing with overruns here.
    
        unprocessedcharacter++;  // increment this
        charreceived = RCREG;  // store the received data    
    }

    // transmit

    if ((PIR1 & 0b00000010) == 0b00000010) {
        // ie TXIF is set, meaning something can be transmitted
        
        if (characters_to_send > 0) {
            // load the register for transmission
            TXREG = transmit_buffer[buffer_start];
            buffer_start++;
            if (buffer_start == buffersize) {
                buffer_start = 0;
            }
            characters_to_send--;
            if (characters_to_send == 0) {
                // turn off the TXEN
                TXSTA = TXSTA & 0b11011111;
                // turn on the TXEN
            }
        }
    }
}

 

The idea is that if a character is received, an interrupt is raised. Your ISR (interrupt service routine) is called, and so you just copy the received character into a global and get out of the way. (The main() loop in this code checks for the “unprocessedcharacter” variable, and decrements it when processed).

The transmit interrupt in the PIC is a little strange. An interrupt is raised by a PIC when it is ready to transmit. So the ISR has to feed the transmit buffer. (I think this is probably better than the alternative, which is for the PIC’s main code to go into a fast loop waiting for the transmit buffer to be empty if there are a lot of characters to transmit). I found that if the ISR doesn’t turn off the transmit function (and so stop the interrupt from being called) when there is nothing to transmit, then it becomes unresponsive.

With the combination of the PIC and RealTerm, and the ISR as above, I was able to write code so that the PIC responded to keypresses and sent info back to the PC on particular keypresses. Great success! Merging this with the LCD display was then meant to be easy…

Serial port talking to PIC driving 74×595 driving LCD

The PIC code flow was meant to be

  1. set up LCD
  2. Wait for serial data
  3. Decode serial data into command or data
  4. Manipulate LCD

In trying to be clever, I set up a set of commands. Typing “D” would get the next character decoded onto the LCD datalines. “E” would send the LCD line enable high, “e” would send it low, “R” would send the LCD RS line (which selected between character and data) high, “r” send it low.

For commands, this worked. I was able to send the commands to turn on a blinking cursor, and line 2. But I was unable to display a character. Putting an LED on the dataline showed that “R” would send it high, and “r” low. I was confused. After a while, I realised that the character “A” was sending the cursor to line 2, position 2, which was the correct data line. It was as though the high character line (RS) was being ignored.

I soldered up a 2nd LCD terminal (previous project couldn’t decided between orange or green background, so bought 2 of each), perhaps thinking that some latent ESD damage had affected that input. Same problem. A new PIC had the same problem. Staring at the LED whilst hammering keys, I found that the RS line was going low with all subsequent serial inputs. But there’s nothing in the code on this…

I still don’t know why. I stared at the code for days. After a while, I hacked the code so nothing sent the line low. But it still went low.  The workaround was to move the RS controlling line to a different PIC port. I am still unsatisfied by this, but it allowed progress to be made.

After this simple change: great success! I was able to send commands to the PIC from a PC (using RealTerm), and got the display working properly. I moved the control level of the code up, so commands from the PC were a conceptual level up; they were “turn display on” rather than “send 01 to display”, “drive line high”. Time to bite the bullet and plug in the bluetooth module…

 

BT module talking to PIC driving 74×595 driving LCD

ACtually, this wasn’t the next step. It sounds good, but I wanted to understand talking to the BT module from an Android device (ie my phone) first. So it went Phone -> BT module -> PC. And after the headbanging of trying to understand why the RS line was not staying up (see above), this went really really smoothly.

I plugged the BT module into a breadboard, and connected it to the Serial to USB cable (remembering that TX on one is RX on the other). I only tried uni-directional, from BT to USB cable, to avoid putting a 5V Serial line onto a 3.3V only BT line. On my phone I installed a BT terminal (I used this one). Text I sent from my phone then appeared in RealTerm. Great Success! I had to pair my phone with the BT module, which “just worked”. I had to read the docs for the passcode, but its a default. (When I deploy this at work, I’ll change the BlueTooth ID and passcode!)

Because this went so well, I swapped the connections over and connected the BT module to the PIC. I also tweaked the PIC code to allow for even less typing, and tried it…

And it almost worked. Things initalized, commands could be sent, but sending a message (which, for a 12 byte string, requries sending M12 first (“M” for message, 12 for the number of bytes to received; everything after that is ignored) only displayed the last character sent. Gah! Messages were possible, but only with extra typing.

This was another annoying debugging moment. I spent a long time not trusting my message receive buffering code, but it was perfect. I tested timing. No. I slept on it. I worried about whether variables were volatile or not. After a lot of headbanging, it was a simple refactoring error. (Working code had been cut’n’pasted into a routine to aid readability, but not all variable names were correctly changed into the function prototypes. It still worked because of globals, almost. Just not with the buffering).

However, it is now fixed. And a screenshot like this from my phone

Screenshot_2016-04-13-21-46-11

gives this sort of response on the hardware

projectblog caption

 

(Still using the USB-Serial cable as it provides a useful regulated 5V supply!)

Phew!

Next steps are :

  1. Move hardware into a box
  2. Custom android code
  3. Full documentation

 

This project also gives a nice extensible base for some other ideas I have. I now have the knowledge to build a many (slow) digital output system with a human or programmatic interface from a PC or BlueTooth-enabled device, which means some of the heavy lifting can be done by phones, or desktop PCs. I’ve also got a useful display system, which can be added to things I want to debug only requiring three lines; LEDs are great for single outputs, but sometimes a text display allows for a lot of internal state information in one go.

The HC-05 BlueTooth device is awesome. It really is a very easy-to-use drop-in  wireless serial comms solution, that adds almost no complexity to the receiving system, but wireless functionality. I’m glad I bought two!

 

 

 

 

 

Matrix LED testing

In the drive to be able to control more and more LEDs, there is the matrix format. Here’s a circuit diag from Kingbright that produce bulk devices. The circuit diagram is:

matrix_diag

Here’s a picture of the device

led_matrix

35 LEDs in an 7 by 5 package, and so only 13 pins. And so can be driven (in theory) by 2 shift registers.

For example, if C1 is 5V, and pin 9 is 0V, then current flows through the top left LED and that LED is lit. In fact, if all of the R1 to R7 are 0V, all 7 LEDs are lit. So as long as the R? are high (i.e. 5V) and C? are low (i.e. 0V) everything is off.

So we can control this by driving a particular column high, and then Rx low for the LEDs we want to be lit. Current will then flow and the LEDs lit. And this can then be done for each column in turn. We can take advantage of the fact that human eyes are, in terms of temporal response, rubbish and just light the LEDs as quickly as we can, it’ll look like a static picture.

HC magic

The 74hc595 shift registers have a bit of magic in them. The outputs can be driven high, and we are used to the idea that a driven high output can supply current, i.e. be a current source. Upto 20mA, which as LEDs are fully lit with 5 to 15mA (dependent on colour), is nice. In addition, an output driven low can sink current. No connection to ground required. So an LED can be placed between two outputs; if one end is driven high, and the other low, it’ll light. Any of the other three cases, the LED would not be lit.

History

A couple of years ago, I built a circuit to test this, using a Kingbright matrix, 2 74595s and a PIC. Due to a shortage of DIP scokets, an excess of enthusiasm, and a lack of planning (read: not drawing a circuti diagram before putting together) some mistakes were made. I traced through what was made, and identified the mistakes.

matrix_errors

Major thing to do here was to identify the mistakes. I then fixed up the board, and then it looked like

matrix_fixed

Code

The code is then simple. With the circuit above, the idea is to drive each column high in turn, and set the rows to low for the LEDs that are wanted to be lit, and high the others. I used the same send_byte_to_595 and display_595() routines that I used for the Spoke Pov project, making sure to send the row first, and then the column. i.e.

void display_5x7_matrix(char v1, char v2, char v3, char v4, char v5) {

    send_byte_to_595(v1);
    send_byte_to_595(0x08);
    display_595();

    send_byte_to_595(v2);
    send_byte_to_595(0x10);
    display_595();

    send_byte_to_595(v3);
    send_byte_to_595(0x20);
    display_595();

    send_byte_to_595(v4);
    send_byte_to_595(0x40);
    display_595();

    send_byte_to_595(v5);
    send_byte_to_595(0x80);
    display_595();
}

The main() is just then a repeated set of calls with the right values

 
{
    v1 = 0b00010000;
    v2 = 0b00100100;
    v3 = 0b01000000;
    v4 = 0b00100100;
    v5 = 0b00010000;

    while ( 1==1 ) {
        display_5x7_matrix(~v1, ~v2, ~v3, ~v4, ~v5);
    }
}

Simples.

The pattern is designed by my daughter as a smily face. And it works!

Demo image, along with design requirements from daughter.

Demo image, along with design requirements from daughter.

Interestingly, the different colours are not as obvious to human eyes as to the camera…

Code for this is on github as [to be filled in]

This was all a test. The idea is to push to a larger, homemade, matrix of LEDs for another project. But this circuit allows a little experimention with the “output enable” control pin to change brightnesses (the subject of a forthcoming post) and a general proof of concept of driving a matrix without having to wire up 35 LEDs…

 

 

Bike Spoke Images; final breadboard?

With the interrupts at least demonstrated (https://astrospanner.wordpress.com/2014/02/02/bike-spoke-images-timer-interrupt-woes/), hall effect switching demonstrated (https://astrospanner.wordpress.com/2014/01/24/magnetic-switching-pov/) and LED control demonstrated (https://astrospanner.wordpress.com/2014/01/27/bike-spoke-images-pic-leds/), two things are true:

  1. all the hardware has been demonstrated to work
  2. conceptually, the “hard” bits of the software have been demonstrated to work.

So there are two more steps; a final software build and a final hardware build.

Feel free to listen to this (http://www.youtube.com/watch?v=9jK-NcRmVcw) whilst reading this post.

Final Software Build

The software is structured into three sections: a timer interrupt routine, a hall effect interrupt routine and a main() routine. It’s generally a good idea for interrupt routines to be quick to execute, so that further interrupts are not missed. As such, the display driving has been moved to the main() routine. The three routines communicate via a set of global variables. The global variables are:

Global variable Timer Switch Main
Counter increment read, reset
Change Display Flag Set Set Read & Reset
DisplayCounter Read, Write
DisplayCounterSet Read Set
ToDisplay Increment Reset Read

Flowcharts for the three sections are

main()

main

hall effect switch

switch

timer

timer

And in words, the idea is whenever the magnet passes the Hall Effect switch, the following things happen:

  1. the number of timer ticks since that last happened, divided by the number of radial lines to display is stored (in “DisplayCounterSet”)
  2. DisplayCounter is reset (to DsiplayCounterSet)
  3. The radial line to display is reset to zero
  4. The zero radial line is displayed

The timer is counting down DisplayCounter, and when it reaches zero, the DisplayCounter is reset to DisplayCounterSet and a new line gets displayed.

Because the wheel rotation speed is changing (reasonably) slowly, this scheme uses the last rotation speed to guess where to display each radial line. If we didn’t do this, he orientation of the displayed image would drift, unless the wheel was going at the exactly correct speed (which would also be dependent on battery voltage and temperature).

Final Breadboard

With the code working, this can be implemented on a breadboard. It’s the same breadboard as used before, just with the addition of the magnetic switch onto pin 4 of the PIC. (Pin 4 is the input only pin of the PIC12f675 so it makes sense to use it as the only input.) For aliveness testing I also added an LED driven by pin 3 and an additional line into the Hall Effect routine to toggle the GPIO so I could check that a) the PIC was doing something and b) all magnet passes were identified.

And it works!

Video here: http://www.youtube.com/watch?v=nfqQzUZzInU

You can see in the video that there is a fast pattern for the first 3 seconds, and then I pass a magnet near the Hall Effect sensor (which is on the bottom right of the board). The pattern then repeats after the next pass at 7 seconds. The pattern certainly repeats.

The pattern is hardcoded to 64 lines. It intends to say “CYCLING ROCKS”. The font is hand designed to fit into the 64 lines to be 8×4 sets, to look like this:

Excel produced image

Excel produced of message

The circuit board (as seen in the video) was actually built a couple of years ago for a 16 pin PIC. Fortunately, the power connections for different PICs are presumably deliberately pin 1 and the last numbered pin, so a 8 pin PIC can be put into the same socket. After wrapping with some duct tape, I then mounted on the front of wheel of my daughter’s bike. (Smallest bike to get into the kitchen work area).

Breadboard on the bike

Breadboard on the bike

The magnet was duct-taped to the fork, and with the lights off, can be tested properly, as can be seen below:

running

This was stable for different rotation speeds. So apart from senses of letters, this can probably be declared a success!

Next steps are to try this on a bike that we can actually cycle along to see what it looks like to a random passersby before going for a full up 24 LED version. (Still slightly worried about fitting all the data into the PIC…)

Bike Spoke Images: Code release

As intended, I’ve setup a github account and repository. The clone url is: https://github.com/astrospanner/pov_project.git

All the code used for the demos so far is on there. Because it was setup after I wrote and debugged most of the code, there’s little history that you would normally associate with a proper version control system.

From now, this is now the public facing repository for all project work that this blog will document.

It’s worth pointing out that I’m using TortiseGit (https://code.google.com/p/tortoisegit/) as a Windows 7 shell extension to help with the commits and pushing. The Dancing Monkeys blog had an excellent easy to follow instruction blog post that I followed to get everything setup. Linky: http://dancingmonkeysaccelerated.blogspot.co.uk/2012/03/git-for-windows-with-tortoisegit-and.html

Enjoy the code! If you think it can be improved; comment, or send me a patch!