arduino,  Microcontrollers

Getting the atMega to Talk to an AT-09

Getting the lights to blink showed that the thing worked, and that we could write and deploy code with input and output. That and a couple of bucks will get us a cup of coffee (but not if we want it from one of those foo-foo chains that can’t tell the difference between “strong” and “burnt” . . .).

Now we want to talk to it. Recall that my long term goal is to have these throughout the yard and garden as monitors and controls, but we want them to tell the central system what they’re doing and observing, and to take instructions from it.

There are many chips out there, but the AT-09 has the advantage of being cheap. *Really* cheap–under $2 mounted on a six-prong board that fits a breadboard, and even further less than two bucks for the raw module if you want to go that way.

I’ve chosen to use the altSoftSerial library for it, which communicates from RX on D8 and TX on D9 (and the RX of D8 goes to the TX of the AT-09, etc.).

A couple of other considerations:

  • Looking ahead to running off of a battery, I will also want to be able to control the power status, so that it doesn’t consume juice listening or advertising except when we tell it to do so.
  • We’re using a nano that has the usb port permanently connected, with no way to turn it off. Later, we will want to run the serial communication from the built in UART, rather than a bit banging library.

Initially, I used the SoftwareSerial library, so here is an example code that successfully talks to the AT-09 unit:

(at the moment, code formatting does not appear to be working properly. If you paste it into the arduino editor and hit ctrl-t, it will reformat for you)

#AT-09_3
#include <SoftwareSerial.h>
//use 11 & 12for RX & TX
int off3 = 0;
int off4 = 0;
int btTx = 12;
int btRx = 11;
SoftwareSerial btSerial(btRx, btTx);
void setup() {
// put your setup code here, to run once:
// input buttons on 3 & 4
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
// LED on 9 & 10
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
//set up the regular serial--really just for testing the bluetooth
Serial.begin(9600);
//wait for it to be ready
while (!Serial) {};
//test it
Serial.println("zap!");
//set up bluetooth serial
btSerial.begin(9600);
//Serial.println("wham!");
btSerial.write("AT\n");
}
void loop() {
if (btSerial.available()) {
//this means serial data available from bt.Serial; uncoming BT data
Serial.write("Data coming:"); Serial.write(btSerial.read()); Serial.println();
}
if (Serial.available()) {
//this would mean that data is available from the serial monitor
Serial.println("Sending: ");
btSerial.write(Serial.read());
}
if ((digitalRead(3) == LOW) && (millis() > off3)) {
//button 3 pressed
off3 = millis() + 1000;
digitalWrite(9, HIGH);
Serial.print("button 3\n");
//Serial.println(off3);
btSerial.write("AT\n");
}
if ((digitalRead(4) == LOW) && (millis() > off4)) {
//button 4 pressed
off4 = millis() + 1000;
digitalWrite(8, HIGH);
Serial.print("button 4\n");
//Serial.println(off4);
btSerial.write("AT");
}
if (millis() > off3) {
digitalWrite(9, LOW);
};
if (millis() > off4) {
digitalWrite( 8, LOW);
};
}

Pretty much all of the code from the button example is here, just for “proof of life”.

The main loop first checks to see if any data is available from the bluetooth. If so, it writes it to the serial port. Similarly, it checks in the other direction, too. Coming up, it will print “ERROR” coming from the bluetooth after “zap.”

It will also respond properly if you type “AT” into the monitor and send it–it responds with “OK”. Any other command, though, is still yielding an error.

For the next iteration, I made some changes.

Button and led pins may have uses in the future, but they take up space on my board and pins on the MCU. Also, the way things are written, I need code for each pair. So the first change adds code to create constant arrays btnPins and ledPins to keep track of them, and nBtns and needs as calculated constants to keep track of how many. I also add an array off[] to keep track of them. (note: There is still a serious bug from earlier programs? Can you catch it? And there are more to come after this point.) There is also a change to AltSoftSerial, meaning pins have to be reassigned, as this library always uses D8 for RX and D9 for TX. Note that it also hijacks the PWM timer for pin 10, which can only be used as a regular digital line.

setup() has been expanded to loop through however many button pins and led pins are actually used and loop through them to get them ready.

The code is included here to show the transition and as a debugging opportunity; it does not work as intended, and the debt code is left intact.

//at09_4
// #include <SoftwareSerial.h>
//include <AltSoftSerial.h>
//the number of buttons and leds
//pins for LEDs and buttons
const int btnPins[] = {3, 4};
const int nBtns = sizeof(btnPins) / sizeof(btnPins[0]);
const int ledPins[] = {5, 6};
const int nLeds = sizeof(ledPins) / sizeof(btnPins[0]);
//initial values for the button time counters
int off[nLeds] = {0};
//we want an altsoftserial. On nano, rx=D8 and TX=D9
AltSoftSerial btSerial;
void setup() {
// put your setup code here, to run once:
//set input btn modes
for (int i = 0; i < nBtns; i++ ) {
pinMode(btnPins[i], INPUT_PULLUP);
Serial.println(btnPins[i]);
}
//
// // input buttons on 3 & 4
// pinMode(3, INPUT_PULLUP);
// pinMode(4, INPUT_PULLUP);
//set input LED modes
for (int i = 0; i < nLeds; i++ ) {
pinMode(ledPins[i], INPUT_PULLUP);
Serial.println(ledPins[i]);
}
// // LED on 5,6
// pinMode(5, OUTPUT);
// pinMode(6, OUTPUT);
//set up the regular serial--really just for testing the bluetooth
Serial.begin(9600);
//wait for it to be ready
while (!Serial) {};
Serial.write("nBtns: ");Serial.println(nBtns);
//test it
Serial.println("zap!");
//set up bluetooth serial
btSerial.begin(9600);
//Serial.println("wham!");
Serial.println("");
btSerial.write("AT\n");
Serial.write("btn ");
Serial.println(btnPins[0]); Serial.write(" _ "); Serial.println(btnPins[1]);
Serial.write("nBtns: ");Serial.println(nBtns);
for (int i=0;i<nBtns;i++){
Serial.write("_"); Serial.write(i) ; Serial.write(" "); Serial.println(btnPins[i]);
}
// delay(2000);exit(0);
}
void loop() {
if (btSerial.available()) {
//this means serial data available from bt.Serial; uncoming BT data
// Serial.write("Data coming:"); Serial.write(btSerial.read()); // Serial.println();
}
if (Serial.available()) {
//this would mean that data is available from the serial monitor
// Serial.println("Sending: ");
btSerial.write(Serial.read());
}
// Serial.println("iterating");
for (int i = 0; i < nBtns; i++) {
//Serial.write("btn_i: "); Serial.println(i);
// delay(10000);
//exit(0);
Serial.write("btn_i: "); Serial.println(i);
Serial.write(" pin:");
Serial.println(btnPins[i]);
Serial.write(" _ ");
//Serial.println(ledPins[i]);
//Serial.println("\n\n");
Serial.println(digitalRead(btnPins[i ]));
if ((digitalRead(btnPins[i]) == LOW) && (millis() > off[i])) {
//btn i was pressed
Serial.write ("btn "); Serial.println(i);
if (i < nLeds) {
//there is a corresponding LED; turn it on until a second from now
off[i] = millis() + 1000;
digitalWrite(ledPins[i], HIGH);
Serial.print("butotn ");
Serial.println(i);
}
switch (i) {
case 0 :
//do these for button 1
break;
case 1 :
//do these for bttn 2
break;
default :
//any default actions
break;
}
}
}
delay(1000);
//exit(0);
for (int i = 0; i < nLeds; i++) { //turn off any expired LED if (millis() > off[i]) {
digitalWrite(ledPins[i], LOW);
};
}
}


Play with this. See which errors you can find. The functional version will be in the next atMega post.

Leave a Reply