HC-05 Bluetooth with Arduino

Some time ago, I bought a couple of HC-05 Bluetooth modules.  They use the CSR Bluecore 04-External single chip Bluetooth system.  ITead Studio has a great little datasheet for the HC-05.

I wanted to be able to configure the device from the Arduino programatically, but according to the documentation you need to power cycle the chip to get it into AT mode (the mode necessary to send AT commands to the module).  Instead, I have found that you can achieve the same result by simple pulling the RESETB pin low for more than 5ms.  In my code below, I have a function enterATMode() that raises PIO11 HIGH, then resets the module so that it will accept AT commands.  Once I have finished setting the device up correctly with AT commands, I pull PIO11 LOW and then reset the device again, using the function enterComMode.

I list the pin connections in the DEFINES at the beginning of each code block.

HC-05 Slave Mode with Arduino:


/*
Copyright Chris Samuelson 2012
*/

#include <SoftwareSerial.h> //Software Serial Port
#define RxD 6
#define TxD 7
#define Reset 5
#define PIO11 8
#define Led 13
#define RTS 4

SoftwareSerial blueToothSerial(RxD,TxD);

void setup()
{
 Serial.begin(9600);
 pinMode(RxD, INPUT);
 pinMode(TxD, OUTPUT);
 pinMode(Led, OUTPUT);
 pinMode(PIO11, OUTPUT);
 digitalWrite(PIO11, HIGH);
 pinMode(Reset, OUTPUT);
 digitalWrite(Reset, LOW);
 pinMode(RTS, INPUT);
 setupBlueToothConnection();
}

void loop()
{
 char recvChar;
 boolean rtsStatus = true;
 while(1){
 if(blueToothSerial.available()){//check if there's any data sent from the remote bluetooth shield
 recvChar = blueToothSerial.read();
 if(recvChar == 'a'){
 digitalWrite(Led, HIGH);
 }
 if(recvChar == 'b'){
 digitalWrite(Led, LOW);
 }
 Serial.print(recvChar);
 }
 if(Serial.available()){//check if there's any data sent from the local serial terminal, you can add the other applications here
 recvChar = Serial.read();
 blueToothSerial.print(recvChar);
 }
 }
}

void setupBlueToothConnection()
{
 enterATMode();
 sendATCommand();
 sendATCommand("UART=57600,0,0");
 sendATCommand("ROLE=0");
 sendATCommand("PSWD=4567");
 sendATCommand("CMODE=1");
}

void resetBT()
{
 digitalWrite(Reset, LOW);
 delay(2000);
 digitalWrite(Reset, HIGH);
}

void enterComMode()
{
 blueToothSerial.flush();
 delay(500);
 digitalWrite(PIO11, LOW);
 resetBT();
 delay(500);
 blueToothSerial.begin(57600);
}

void enterATMode()
{
 blueToothSerial.flush();
 delay(500);
 digitalWrite(PIO11, HIGH);
 resetBT();
 delay(500);
 blueToothSerial.begin(38400);

}

void sendATCommand(char *command)
{
 blueToothSerial.print("AT");
 if(strlen(command) > 1){
 blueToothSerial.print("+");
 blueToothSerial.print(command);
 delay(100);
 }
 blueToothSerial.print("\r\n");
}

void sendATCommand()
{
 blueToothSerial.print("AT\r\n");
 delay(100);
}

HC-05 Master Mode

/*
Copyright Chris Samuelson 2012</pre>
*/

#include <SoftwareSerial.h> //Software Serial Port
#define RxD 6
#define TxD 7
#define Reset 5
#define PIO11 8
#define Led 13
#define RTS 4

SoftwareSerial blueToothSerial(RxD,TxD);

void setup()
{
 Serial.begin(9600);
 pinMode(RxD, INPUT);
 pinMode(TxD, OUTPUT);
 pinMode(Led, OUTPUT);
 pinMode(PIO11, OUTPUT);
 digitalWrite(PIO11, HIGH);
 pinMode(Reset, OUTPUT);
 digitalWrite(Reset, LOW);
 pinMode(RTS, INPUT);
 setupBlueToothConnection();
}

void loop()
{
 char recvChar;
 boolean rtsStatus = true;
 while(1){
 blueToothSerial.print("a");
 delay(500);
 blueToothSerial.print("b");
 delay(500);
 if(blueToothSerial.available()){//check if there's any data sent from the remote bluetooth shield
 recvChar = blueToothSerial.read();
 if(recvChar == 'a'){
 digitalWrite(Led, HIGH);
 }
 if(recvChar == 'b'){
 digitalWrite(Led, LOW);
 }
 Serial.print(recvChar);
 }
 if(Serial.available()){//check if there's any data sent from the local serial terminal, you can add the other applications here
 recvChar = Serial.read();
 blueToothSerial.print(recvChar);
 }
 if(digitalRead(RTS)){
 if(!rtsStatus){
 rtsStatus = true;
 Serial.print("rts changed true");
 }
 }else{
 if(rtsStatus){
 rtsStatus = false;
 Serial.print("rts changed false");
 }
 }
 }
}

void setupBlueToothConnection()
{
 enterATMode();
 sendATCommand();
 sentATCommand("UART=57600,0,0");
 sendATCommand("ROLE=1");
 sendATCommand("PSWD=0000");
 sendATCommand("PAIR=0018,e4,0c680a");
 sendATCommand("BIND=0018,e4,0c680a");
 sendATCommand("CMODE=0");
 enterComMode();
}

void resetBT()
{
 digitalWrite(Reset, LOW);
 delay(2000);
 digitalWrite(Reset, HIGH);
}

void enterComMode()
{
 blueToothSerial.flush();
 delay(500);
 digitalWrite(PIO11, LOW);
 resetBT();
 delay(500);
 blueToothSerial.begin(57600);
}

void enterATMode()
{
 blueToothSerial.flush();
 delay(500);
 digitalWrite(PIO11, HIGH);
 resetBT();
 delay(500);
 blueToothSerial.begin(38400);

}

void sendATCommand(char *command)
{
 blueToothSerial.print("AT");
 if(strlen(command) > 1){
 blueToothSerial.print("+");
 blueToothSerial.print(command);
 delay(100);
 }
 blueToothSerial.print("\r\n");
}

void sendATCommand()
{
 blueToothSerial.print("AT\r\n");
 delay(100);
}
<pre>

ATMega32u4 / Arduino Leonardo Charlieplexing

I created a small charlieplexing demo for the Arduino Leonardo that uses a frame buffer to store the pixel data, and a timer interrupt to update the display.  This is all done using an ATMega32u4 breakout board by Mattair Tech LLC http://www.mattairtech.com/index.php/featured/mt-db-u4.html.  I program it using the Arduino Leonardo stack.  For this quick demonstration I used the Charlieplex library from http://arduino.cc/playground/Code/Charlieplex.  I plan to replace this with a solution more specific to my hardware to reduce the required clock cycles.  For the timer interrupt routine I used a library called TimerOne from http://arduino.cc/playground/Code/Timer1.

Why Charlieplexing and how does it work?

Using charlieplexing you can control more LEDs with fewer pins than you could with regular direct drive methods.  For example, in the demo board I drive 12 LEDs with 4 micro controller pins.  It also reduces other components, in the demo board I only need 4 resistors for 12 LEDs.

There are some costs to using charlieplexing though.  It is more complex to design the circuit and you can only light one LED at a time.

Charlieplexing is fairly simple once you understand a couple of basic concepts:

1) LEDs only light when electricity is passed through them in one direction.

2) You only light one LED at a time, to make more than one LED appear to be on at any time you simply flash them very quickly (greater than 50hz).

3) Micro controller pins typically have 3 different states: HIGH, LOW, HIGH IMPEDANCE (INPUT).  In Arduino you set the pins state in 2 different ways.  To set the pin as INPUT you use pinMode(pin,INPUT).  To set the pin as HIGH or LOW, first set the pins direction to OUTPUT with pinMode(pin,OUTPUT) then set the pins value with digitalWrite.  To set pin 5 high would be: pinMode(5,OUTPUT); digitalWrite(5,HIGH).

Here is the most basic example, 2 LEDs with 2 micro controller pins:

In this example, electricity can either flow from Pin 1 to Pin 2 through the LEDs or from Pin 2 to Pin 1 through the LEDs.

To light LED1 in this example you would set pin1 HIGH and pin2 LOW.  To light LED2 you would do the opposite and set pin1 LOW and pin2 HIGH.  With only 2 pins we don’t need to set any pins to high impedance yet.

Here is a slightly more complex example, this time 3 micro controller pins:

In this example, electricity can either flow from Pin 1 to Pin 2 through the LEDs or from Pin 2 to Pin 1 through the LEDs, just like in the first example.  But, now it can also flow from pin2 to pin3, pin3 to pin2, pin1 to pin3 and pin3 to pin1.  

That means we can light up to 6 different LEDs.  This brings up some good questions though.  If we set pin1 high and pin2 low to light LED1, what do we set pin3 to?  If pin3 is high then LED4 will also light, if we set pin3 low then LED6 will also light.  We set pin3 to INPUT, this is similar to disconnecting the pin.  It will not sink or source current when it is set to INPUT, but instead appears to be a very large resistance.

Let’s try each LED:

LED1 => pin1 = HIGH, pin2 = LOW, pin3 = INPUT

LED2 => pin1 = LOW, pin2 = HIGH, pin3 = INPUT

LED3 => pin1 = INPUT, pin2 = HIGH, pin3 = LOW

LED4 => pin1 = INPUT, pin2 = LOW, pin3 = HIGH

LED5 => pin1 = HIGH, pin2 = INPUT, pin3 = LOW

LED6 => pin1 = LOW, pin2 = INPUT, pin3 = HIGH

There are some other great resources on the web that help to explain charlieplexing if you still have questions, one of my favorites is UziMonkeys explanation.

You can see the way that the 3 pin circuit is laid out, that you basically have 3 pairs of LEDs.  A pair between pins 1 and 2, a pair between pins 2 and 3 and a pair between pins 1 and 3.  Each pair can be powered forward or reverse to give you 6 total LEDs.

Circuit Design

I laid out this circuit with Eagle CAD.  Routing took a minute to think through, as I wanted to make this as close to a 1 layer board as I could.  As it stands, I only have one jumper on the board.

Circuit Board Creation

I printed out the circuit board on parchment paper with my laser printer.  Then transferred the toner to my copper clad board with a laminator.  For etchant I used the trusty hydrochloric acid and peroxide formula.   I will post a blog entry soon about my preferred method for creating PCBs.

Download Charlieplex Eagle Files ZIP

The code and schematic follow.

#include <TimerOne.h>

#include <Charlieplex.h>

#define NUMBER_OF_PINS 4
#define NUMBER_OF_LEDS 12
int led = A0;

charliePin cp[] = {
 {
 0,2 }
 ,{
 0,3 }
 ,{
 1,3 }
 ,{
 2,0 }
 ,{
 3,0 }
 ,{
 3,1 }
 ,{
 0,1 }
 ,{
 1,2 }
 ,{
 2,3 }
 ,{
 1,0 }
 ,{
 2,1 }
 ,{
 3,2 }
};

int state[NUMBER_OF_LEDS];

int i = 0;
int j = 0;

byte pins[] = {
 8,9,10,5};
Charlieplex charlieplex = Charlieplex(pins,NUMBER_OF_PINS);

void setup() {
 // open the serial port:
 Serial.begin(9600);
 // pinMode(led,OUTPUT);
 // digitalWrite(led,HIGH);
 for(i=0;i<NUMBER_OF_LEDS;i++){
 state[i] = LOW;
 }
 Timer1.initialize(800);
 Timer1.attachInterrupt(framewriter);
 // initialize control over the keyboard:
 //Keyboard.begin();

for(j=0;j<NUMBER_OF_LEDS;j++){
 state[j]=HIGH;
 if(j>0){
 state[j-1]=LOW;
 }
 delay(100);
 }
 state[NUMBER_OF_LEDS-1] = LOW;
}

void loop() {
 // check for incoming serial data:
 if (Serial.available() > 0) {
 // read incoming serial data:
 char inChar = Serial.read();
 // Type the next ASCII value from what you received:
 switch(inChar){
 case 'z':
 for(j=0;j<NUMBER_OF_LEDS;j++){
 state[j]=LOW;
 }
 charlieplex.clear();
 break;
 case 'a':
 if(state[0] == HIGH){
 state[0] = LOW;
 }
 else{
 state[0] = HIGH;
 }
 break;
 case 'b':
 if(state[1] == HIGH){
 state[1] = LOW;
 }
 else{
 state[1] = HIGH;
 }
 break;
 case 'c':
 if(state[2] == HIGH){
 state[2] = LOW;
 }
 else{
 state[2] = HIGH;
 }
 break;
 case 'd':
 if(state[3] == HIGH){
 state[3] = LOW;
 }
 else{
 state[3] = HIGH;
 }
 break;
 case 'e':
 if(state[4] == HIGH){
 state[4] = LOW;
 }
 else{
 state[4] = HIGH;
 }
 break;
 case 'f':
 if(state[5] == HIGH){
 state[5] = LOW;
 }
 else{
 state[5] = HIGH;
 }
 break;
 case 'g':
 if(state[6] == HIGH){
 state[6] = LOW;
 }
 else{
 state[6] = HIGH;
 }
 break;
 case 'h':
 if(state[7] == HIGH){
 state[7] = LOW;
 }
 else{
 state[7] = HIGH;
 }
 break;
 case 'i':
 if(state[8] == HIGH){
 state[8] = LOW;
 }
 else{
 state[8] = HIGH;
 }
 break;
 case 'j':
 if(state[9] == HIGH){
 state[9] = LOW;
 }
 else{
 state[9] = HIGH;
 }
 break;
 case 'k':
 if(state[10] == HIGH){
 state[10] = LOW;
 }
 else{
 state[10] = HIGH;
 }
 break;
 case 'l':
 if(state[11] == HIGH){
 state[11] = LOW;
 }
 else{
 state[11] = HIGH;
 }
 break;
 case 'm':
 for(j=0;j<NUMBER_OF_LEDS;j++){
 state[j]=HIGH;
 delay(100);
 }
 break;
 case 'n':
 for(j=0;j<NUMBER_OF_LEDS;j++){
 state[j]=LOW;
 delay(100);
 }
 break;
 case 'o':
 for(j=0;j<NUMBER_OF_LEDS;j++){
 state[j]=LOW;
 }
 for(j=0;j<NUMBER_OF_LEDS;j++){
 state[j]=HIGH;
 if(j>0){
 state[j-1]=LOW;
 }
 delay(100);
 }
 state[NUMBER_OF_LEDS-1]=LOW;
 break;
 }

// Serial.write(inChar+1);
 }

}

void framewriter()
{
 if(i++==NUMBER_OF_LEDS){
 i=0;
 }
 charlieplex.clear();
 charlieplex.charlieWrite(cp[i],state[i]);

}

MSP430 programmer from TI samples and spare parts


I’m working on a ECG project utilizing an msp430fg437 for DSP. In order to get that project started I needed an msp430 FET. I’d heard of the GoodFET DIY FETs so I started there, I’ve ordered the actual GoodFET41 board, and I’ll put that together when it arrives. In the mean time I really wanted to get started, and I already had samples of the msp430f2618 that the GoodFET uses. My favorite FTDI breakout board the Mikroe USB UART Board ($11 at Mouser) has the extra pins broken out that are needed to program the msp430f2618 through the serial bootloader that it ships with.

I mounted an msp430f2618 on a breakout board, added a few header pins, connected it to the ft232rl breakout and ran the GoodFET software. There were a couple of gotchas:
1) The Mikroe USB UART Board labels the pins backwards. RX is actually the pin the Transmits from the FTDI chip, and is meant to be connected to the MCU’s RX pin. Similarly TX receives. Even more strangely RTS and CTS are flipped, they really mean MCU RTS and MCU CTS.
2) I’m not a big Python user, and it took me a bit to get the required Python dependancies installed on my Mac. Turns out there is this thing called ‘easy_install’. $ easy_install pyserial
3) You can see in the GoodFET41 schematic that the serial lines from the FTDI chip are connected to 2 different pins on the 2618. Pins 13 (TXD) and 22 (RXD) are the Boot Strap Loader serial pins, and pins 32 (TXD) and 33 (RXD) are the regular MCU UART pins.
4) Be sure to include some decoupling caps, one on the msp430f2618 board and some on the target boards.