Metallurgy 101 - AVR UART

This is a continuation of my Robot Metallurgy 101 – AVR Lesson Journal

I started looking through Newbie Hack’s tutorials on AVR trying to work up the energy to tackle First LCD Program. Many don’t know this, but I despise workings with LCDs. I think it is two parts, one, I live in a world with high-resolution screens embedded in everything from coffee-machines to toilets. Trying to settle with an old school LCD doesn’t cut it for me. Furthermore, wiring a non-serial interface LCD is a ever loving pain.

But looking at the rest of the Newbie Hack tutorials I knew I would need some way to display information from the ATtiny1634. I thought about it and compromised: I’d focus on UART next. That way I could display information on my desktop screen.

I began reading about UART on AVR; here are some of the good ones I found,

  1. Newbie Hack’s One Way Communication
  2. Newbie Hack’s Two way Communication
  3. maxEmbedded’s USART

After reading the articles I opened up the ATtiny1634 datasheet and decided I would start by trying to output “ALABTU” to a serial-port into Real Term.

It took me maybe an hour or two to get something working; here is what I learned along the way.

1. AVR UART is Easy.

The following code sets the baud rate on the ATtiny 1634 using the UBBR chart from the datasheet, then, transmits the letter “A.”

UART Code v01

//
// UART Example on the ATtiny1634 using UART0.
// C. Thomas Brittain
// letsmakerobots.com

#define F_CPU 8000000    // AVR clock frequency in Hz, used by util/delay.h
#include <avr/io.h>
#include <util/delay.h>
// define some macros
#define UBBR 51 // 9600, .02%

// function to initialize UART
void uart_init (void)
{
	/* Set baud rate */
	UBRR0H = (unsigned char)(UBBR>>8);
	UBRR0L = (unsigned char)UBBR;
	/* Enable receiver and transmitter */
	UCSR0B = (1<<RXEN0)|(1<<TXEN0);
	/* Set frame format: 8data, 1stop bit */
	UCSR0C = (1<<USBS0)|(1<<UCSZ00)|(1<<UCSZ01);   // 8bit data format
}

void USART_Transmit( unsigned char data )
{
	/* Wait for empty transmit buffer */
	while ( !( UCSR0A & (1<<UDRE0)) );

	/* Put data into buffer, sends the data */
	UDR0 = data;
}

int main()
{
	uart_init();

	while(1){

		USART_Transmit(0x41);
	}
}
  • Line 10: This creates a macro for the UART Baud Rate Register (UBBR). This number can be calculated using the formula on page 148 of the datasheet. It should be: UBBR = ((CPU_SPEED)/16DESIRED_BAUD)-1. For me, I wanted to set my rate to 9600, therefore: UBBR = (8,000,000/169600)-1; Or: UBBR = (8,000,000/153,600)-1 = **51.083. **It can have a slight margin of error, and since we can’t use a float, I rounded to 51.

  • We then setup of function to initialize the UART connection. Lines 16-17 load our calculated baud rate into a register that will actually set the speed we decided upon. This is done by using four bits from the UBBR0L and UBBR0H registers. If the » is unfamiliar to you, it is the right-shift operator and works much like the left-shift, but yanno, in the other direction.

  • Still in initialization, line 19 enables both the RX0 and the TX0 pins (PA7 and PB0 respectively). I’m not using the TX0 pin yet, but I figured I might as well enable it since I’ll use it later.

  • Line 21 sets the bits to tell the Tiny1634 what sort of communication we want. We want 8 bit, non-parity, 1 stop bit. Enabling USBS0, UCSZ00 and UCSZ01 give us these values..

  • Line 24 is the beginning of the function that’ll transmit our data. Line 27 checks to see if the ATtiny1634 is finished transmitting before giving it more to transmit. The UDRE0 is a bit on the UCSR0A register that is only clear when the transmit buffer is clear. So, the while ( !(UCSR0A & (1«UDRE0)); checks the bit, if it is not clear, it checks it again, and again, until it is. This is a fancy pause, which is dependent on the transmit buffer being clear. Line 30 is where the magic happens. The UDR0 is the transmit register, whatever is placed in the register gets shot out the TX line. Here, we are passing the data that was given to the USART_Transmit function when it is called.

  • Line 39 is passing the hex value for the character “A” to the transmit function.

This was a bit easier than expected.

Here was the output from Code v01.

After a little more tweaking and watching Newbie Hack’s video on sending strings to an LCD, I adapted NH’s code to be used by my UART_Transmit() function I ended with a full string of “ALABTU!” on the serial monitor.

I did this by creating a function called Serial_Print, which is passed a character array (string). StringOfCharacters is a pointer and will be passing each character to the UART transmission. Pointers are simply variables that point to the contents of other variables. They are highly useful when you are looking at the information contained in a variable rather than changing variables’ data. Newbie Hack did an excellent job explaining pointers.

Now, whenever the Serial_Print function is called it starts the loop contained. The loop (line 60, code v02) continues to point out each value contained in the string until it comes across a “0” at which point it exits the loop, and subsequently, the function call.

UART Code v02

The above code provided the following output in the serial monitor. (ALABTU!)

At this point my simple mind was quite pleased with its trite accomplishments and I saw building a library out of my code being pretty easy. But a few problems I had to solve first:

A. Dynamic baud rate initialization.

In Arduino C Serial.begin(9600) initializes the serial connection and sets the baud rate. This is dynamic regardless of running an Arduino Uno at 1mhz or Arduino Mega at 16mhz. I wanted the same functionality; being able to set the baud rate by passing it to the intialization function, uart_init().

I solved this by adding the formula in the uart_init() function (see lines 21 and 38 of code v03). In short, the F_CPU macro contains whatever speed the microcontroller is set, in my case 8mhz, and the user knows what baud rate he wants the code set, so I had all the pieces for to solve the UBBR equation. I made F_CPU part of the calculation and allowed the uart_init() to pass the desired baud rate to the formula. This allowed me to set the baud rate simply by passing the uart_init() function whatever baud rate I wanted. e.g., uart_init(9600);

B. Carriage-return and line-feed at end-of-transmission (EOT).

In Arduino C every time you send serial data, Serial.print(“What’s up mother blinkers!?”), there are two characters added. If you are as new to the world of microcontrollers as me, you may have had headaches finding where these extra characters came from whenever you printed something serially. Arduino C’s Serial.Print() function automatically adds the carriage-return and line-feed characters. In ASCII that’s, “13” and “10” and in hex, “0x0A” and “0x0D” respectively. Arduino C does this, I believe, as a protocol flagging the end of a transmission. This is helpful for the serial receiver to parse the data.

To solve this I simply created two functions CR() and LF() that would transmit the hex code for the line-feed character and the carriage-return. I went this route because not every serial devices excepts them, for instance, the HM-10 that I’m in a love-hate with excepts no characters following the AT commands you send it. I wanted an easy way to send these characters, but not so embedded I had to pull my hair out trying not to send them.

The following code is what I ended with,

UART Code v03

The above code provided the following output. Notice my serial monitor automatically recognized the CR and LF character, which is why “ALABTU!” is one per line, and always left-justified. Booyah!

Ok. I’m not done yet, here is what I’ll be working on in the evening over the next few days,

Receiving data is a little more complex…a little.

2. RX is less easy

I started by reviewing Newbie Hack’s code One Way Communication from Chip-to-Chip, more specifically, his code about the receiving chip. I skipped the part about intilization, since I’d already done that and went straight to his receiving code,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
include <avr/io.h>
int main(void)
{
	DDRB |= (1 << PINB0);

	//Communication UART specifications (Parity, stop bits, data bit length)
	int UBRR_Value = 25; //This is for 2400 baud
	UBRR0H = (unsigned char) (UBRR_Value >> 8);
	UBRR0L = (unsigned char) UBRR_Value;
	UCSR0B = (1 << RXEN0) | (1 << TXEN0);
	UCSR0C = (1 << USBS0) | (3 << UCSZ00);

	unsigned char receiveData;
	while (1)
	{
		while (! (UCSR0A & (1 << RXC0)) );

		receiveData = UDR0;

		if (receiveData == 0b11110000) PORTB ^= (1 << PINB0);
	}
}

This code receives data and turns on/off a LED if anything was received. It doesn’t concern itself with the values received, just whether something was received.

I was able to replicate this code and get the LED to switch states, but I quickly noticed a problem. The While loop on line 16 is stuck in checking to see if anything has been received, continuously. The problem is apparent; this freezes the microcontroller from doing anything else. Damnit.

Alright, need a different solution; sadly, the solution was something I’d been avoiding for a year, the use of interrupts.

I’m not the sharpest when it comes to electronics, before July 2012 all I’d ever done with electronics was turned’em on and checked Facebook. (By the way, up yours Facebook.) Since my hardware education began I’ve avoided learning about interrupts because they’ve intimidated me.

I won’t go into interrupts here, since I’m just learning about them. But I’ll mention there are two types, internal and external.

Internal interrupts are generated by the internal hardware of a microcontroller and are called software interrupts, because they are genereated by the CPU as a result of how it is coded. External interrupts are voltages delivered to a pin on the microcontroller. Also, interrupts essentially cause the CPU to put a bookmark in the code it was reading, run over and take care of whatever, then when finished, come back to the bookmarked code and continues reading.

That stated, I’d refer you to Newbie Hack’s tutorials on AVR interrupts. It’s excellent. Also, Abcminiuser over at AVR Freaks provided an excellent tutorial on AVR interrupts.

Ok. Back to my problem.

So, I dug in the ATtiny1634 datasheet (pg 168) and found the ATtiny1634 has an interrupt that will fire whenever the RX data buffer is full. To activate this interrupt we have to do two things, enable global interrupts and set the RXCIE0 bit on the UCSR0B register. This seemed pretty straight forward, but I found a AVR Freaks tutorial that helped explain it anyway.

Caveat, I’m learning to re-read which register a bit is found. Occasionally, I’m finding myself frustrated a piece of code is not working, only to realize I’m initializing a bit on an incorrect port. For example, UCSR0D |= (1<<RXCIE0) will compile fine, but it would actually be enabling the bit RXSEI, which is the bit you set to enable an interrupt at the start of a serial data receive. This happens because the names of registers and bits are part of the AVR Core library, but they are simply macros for numbers. In the case of RXCIE0, it actually represents 7, so coding UCSR0D |= (1<<RXCIE0) is simply setting the 7th bit on the wrong register. Not that I did that or something.

Alright, I now have the interrupt setup for when the ATtiny1634 is done receiving a byte.

UART Code v04

Of course, I didn’t add a character to character array conversion, yet. I’m not sure if I want to add this to current function. I personally would rather handle my received characters on a project specific basis. But it should really be as simple as adding character array, then a function to add each character received to the array until it is full. Then, decide what to do when the character array is full.

But Code v04 gave me the following output:

Each time the letter “A” is sent from the serial terminal a RX interrupt event occurs. The interrupt transfers the byte to a variable that is then sent right back out by the Serial_Print() function. Thus, echoing the data you send it.

3. Fully Interrupted

Ok, so, interrupts are a little tricky. Well, one trick. When you are using an interrupt that modifies a variable anywhere else your main that modifies the same variable, you’ll need to disable the interrupt before the modification. It prevents corrupt or incomplete data.

Also, I am using a poor man’s buffer. It’s a simple buffer that overwrites itself and requires an end-of-transmission character, in my case, a “.” from the transmitter to know where to cap the buffer. Still, I believe this will work for a lot of what I’d like to use it.

I do foresee a problem when I enable the second UART on the Tiny1634, since really, only one RX interrupt can run the show. We’ll see. I’m a little tired to detail things here, but here is the code I ended with and I tried to comment the hell out of it.

UART Code v05

One of the other things I did was enable the sleep mode on the Tiny1634. It is setup on line 39 and part of the main loop. It wakes on receiving serial data. I’ve not tested the power consumption, but this is supposed to make the chip drop down to ~5uA.

Nifty right? :)

Ok, code for the second UART.

UART Code v06

I was surprised. The interrupts didn’t seem to trip each other up. Of course, I only did a simple test of sending data from one terminal into the ATtiny1634 and having it come out on the other terminal. This would be: Data–>RX0—>TX1 and Data–>RX1–>TX0

So, there really shouldn’t be any reason the code would trip out, since the RX0 and RX1 interrupts aren’t firing at the same time. I’ll create a library from this code, and as I start using the library in applications I’ll do more debugging and improvement. Also, if anyone is bored and wants to critique the code, I’ve got my big boy pants on, I’d appreciate the criticism.

4. All Together!

It only took me 30 minutes or so to convert the UART code to a library. Here it is, a UART library consisting of 12 functions.

  1. USART_init0()
  2. USART_init1()
  3. USART_Transmit0()
  4. USART_Transmit1()
  5. Serial_Print0()
  6. Serial_Print1()
  7. ClearBuffer0();
  8. ClearBuffer1();
  9. LF0()
  10. LF1()
  11. CR0()
  12. CR1()

Functions numbered 0 relate to serial lines 0, which are pins PA7 (Rx0) and PB0 (Tx0). The functions numbered 1 are serial lines 1, which are pins PB1 (Rx1) and PB2 (Tx1).

USART_init

  • Initializes a serial lines. Enables TX and RX pins, assigns the baud rate, and enables RX interrupt on receive. It also sets the communication as 8 bit, 1 stop-bit, and non-parity.

USART_Transmit

  • Will transmit a single character.

Serial_Print

  • Prints a string.

ClearBuffer

  • Empties the receiving buffer.

LF and CR

  • Transmit a line-feed or carriage-return character.

This is the library code: 1634_UART.h

#ifndef	UART_1634
#define UART_1634

#include <avr/interrupt.h>  //Add the interrupt library; int. used for RX.

//Buffers for UART0 and UART1
//USART0
char ReceivedData0[32];	//Character array for Rx data.
int ReceivedDataIndex0;	//Character array index.
int rxFlag0;			//Boolean flag to show character has be retrieved from RX.

//USART1
char ReceivedData1[32];	//Character array for Rx data.
int ReceivedDataIndex1;	//Character array index.
int rxFlag1;			//Boolean flag to show character has be retrieved from RX.

//Preprocessing of functions.  This allows us to initialize functions
//without having to put them before the main.
void USART_init0(int BUADRATE);
void USART_Transmit0( unsigned char data);
void Serial_Print0(char *StringOfCharacters);
void clearBuffer0();

void USART_init1(int BUADRATE);
void USART_Transmit1( unsigned char data);
void Serial_Print1(char *StringOfCharacters);
void clearBuffer1();

//EOT characters.
void LF0();
void CR0();

//EOT characters.
void LF1();
void CR1();

// function to initialize UART0
void USART_init0(int Desired_Baudrate)
{
	//Only set baud rate once.  If baud is changed serial data is corrupted.
	#ifndef UBBR
	//Set the baud rate dynamically, based on current microcontroller
	//speed and the desired baud rate given by the user.
	#define UBBR ((F_CPU)/(Desired_Baudrate*16UL)-1)
	#endif

	//Set baud rate.
	UBRR1H = (unsigned char)(UBBR>>8);
	UBRR1L = (unsigned char)UBBR;

	//Enables the RX interrupt.
	//NOTE: The RX data buffer must be clear or this will continue
	//to generate interrupts. Pg 157.
	UCSR1B |= (1<<RXCIE1);

	//Enable receiver and transmitter
	UCSR1B |= (1<<RXEN1)|(1<<TXEN1);

	//Set frame format: 8data, 1 stop bit
	UCSR1C |= (1<<UCSZ00)|(1<<UCSZ01);   // 8bit data format

	//Enables global interrupts.
	sei();
}

// Function to initialize UART1
void USART_init1(int Desired_Baudrate)
{
	//Only set baud rate once.  If baud is changed serial data is corrupted.
	#ifndef UBBR
		//Set the baud rate dynamically, based on current microcontroller
		//speed and the desired baud rate given by the user.
		#define UBBR ((F_CPU)/(Desired_Baudrate*16UL)-1)
	#endif

	//Set baud rate.
	UBRR0H = (unsigned char)(UBBR>>8);
	UBRR0L = (unsigned char)UBBR;

	//Enables the RX interrupt.
	//NOTE: The RX data buffer must be clear or this will continue
	//to generate interrupts. Pg 157.
	UCSR0B |= (1<<RXCIE0);

	//Enable receiver and transmitter
	UCSR0B |= (1<<RXEN0)|(1<<TXEN0);

	//Set frame format: 8data, 1 stop bit
	UCSR0C |= (1<<UCSZ00)|(1<<UCSZ01);   // 8bit data format

	//Enables global interrupts.
	sei();
}

//USART0
void USART_Transmit0( unsigned char data )
{
	//We have to disable RX interrupts.  If we have
	//an interrupt firing at the same time we are
	//trying to transmit we'll lose some data.
	UCSR0B ^= ((1<<RXEN0)|(1<<RXCIE0));

	//Wait for empty transmit buffer
	while ( !( UCSR0A & (1<<UDRE0)) );

	//Put data into buffer, sends the data
	UDR0 = data;

	//Re-enable RX interrupts.
	UCSR0B ^= ((1<<RXEN0)|(1<<RXCIE0));

}

//USART1
void USART_Transmit1( unsigned char data )
{

	//We have to disable RX interrupts.  If we have
	//an interrupt firing at the same time we are
	//trying to transmit we'll lose some data.
	UCSR1B ^= ((1<<RXEN1)|(1<<RXCIE1));

	//Wait for empty transmit buffer
	while ( !( UCSR1A & (1<<UDRE1)) );

	//Put data into buffer, sends the data
	UDR1 = data;

	//Re-enable RX interrupts.
	UCSR1B ^= ((1<<RXEN1)|(1<<RXCIE1));

}

//This functions uses a character pointer (the "*" before the StringOfCharacters
//makes this a pointer) to retrieve a letter from a temporary character array (string)
//we made by passing the function "ALABTU!"

//USART0
void Serial_Print0(char *StringOfCharacters){
	UCSR0B ^= ((1<<RXEN0)|(1<<RXCIE0));

	//Let's do this until we see a zero instead of a letter.
	while(*StringOfCharacters > 0){

		//This function actually sends each character, one by one.
		//After a character is sent, we increment the pointer (++).
		USART_Transmit0(*StringOfCharacters++);
	}
	//Re-enable RX interrupts.
	UCSR0B ^= ((1<<RXEN0)|(1<<RXCIE0));
}

//USART1
void Serial_Print1(char *StringOfCharacters){
	UCSR1B ^= ((1<<RXEN1)|(1<<RXCIE1));

	//Let's do this until we see a zero instead of a letter.
	while(*StringOfCharacters > 0){

		//This function actually sends each character, one by one.
		//After a character is sent, we increment the pointer (++).
		USART_Transmit1(*StringOfCharacters++);
	}
	//Re-enable RX interrupts.
	UCSR1B ^= ((1<<RXEN1)|(1<<RXCIE1));
}

//USART0
void clearBuffer0(){
	//Ugh.  A very inefficient way to clear the buffer. :P
	ReceivedDataIndex0=0;
	for (unsigned int i = 0; i < 64;)
	{
		//We set the buffer to NULL, not 0.
		ReceivedData0[i] = 0x00;
		i++;
	}
}

//USART1
void clearBuffer1(){
	//Ugh.  A very inefficient way to clear the buffer. :P
	ReceivedDataIndex1=0;
	for (unsigned int i = 0; i < 64;)
	{
		//We set the buffer to NULL, not 0.
		ReceivedData1[i] = 0x00;
		i++;
	}
}

void LF0(){USART_Transmit0(0x0A);}  //Function for sending line-feed character.
void CR0(){USART_Transmit0(0x0D);}  //Function for sending carriage-return character.

void LF1(){USART_Transmit1(0x0A);}  //Function for sending line-feed character.
void CR1(){USART_Transmit1(0x0D);}  //Function for sending carriage-return character.

ISR(USART0_RX_vect){
	//RX0 interrupt

	//Show we have received a character.
	rxFlag0 = 1;

	//Load the character into the poor man's buffer.
	//The buffer works based on a end-of-transmission character (EOTC)
	//sent a the end of a string.  The buffer stops at 63 instead of 64
	//to always give room for this EOTC.  In our case, "."
	if (ReceivedDataIndex0 < 63){
		//Actually pull the character from the RX register.
		ReceivedData0[ReceivedDataIndex0] = UDR0;
		//Increment RX buffer index.
		ReceivedDataIndex0++;
	}
	else {
		//If the buffer is greater than 63, reset the buffer.
		ReceivedDataIndex0=0;
		clearBuffer0();
	}
}

ISR(USART1_RX_vect){
	//RX1 interrupt
	PORTA ^= (1 << PINA6);
	//Show we have received a character.
	rxFlag1 = 1;

	if (ReceivedDataIndex1 < 63){
		//Actually pull the character from the RX register.
		ReceivedData1[ReceivedDataIndex1] = UDR1;
		//Increment RX buffer index.
		ReceivedDataIndex1++;
	}
	else {
		//If the buffer is greater than 63, reset the buffer.
		ReceivedDataIndex1=0;
		clearBuffer1();
	}
}

#endif

Really, it is all the functions moved over to a header file (.h). One thing I’ll point out, the #ifndef makes sure the header file is not included twice, but I was getting an error with it for awhile, come to find out, you cannot start #define name for #ifndef with a number, e.g.,

  1. #ifndef 1634_UART – This will not work.
  2. #ifndef UART_1634 – Works great!

Eh. Devil’s in the details.

Ok, here is a program that utilizes the library.

Code v07

// UART Example on the ATtiny1634 using UART0.
// C. Thomas Brittain
// letsmakerobots.com
#define F_CPU 8000000UL		//AVR clock frequency in Hz, used by util/delay.h
#include <avr/io.h>			//Holds Pin and Port defines.
#include <util/delay.h>		//Needed for delay.
#include <avr/sleep.h>		//Needed for sleep mode.
#include "1634_UART.h"

// Main
int main()
{
	//Setup received data LED.
	DDRA |= (1 << PINA6);

	//Light LED on PA6 to show the chip has reboot.
	PORTA ^= (1 << PINA6);
	_delay_ms(500);
	PORTA ^= (1 << PINA6);

	//Initialize the serial connection and pass it a desired baud rate.
	USART_init0(19200);
	USART_init1(19200);

	//Set Sleep
	set_sleep_mode(SLEEP_MODE_IDLE);

	//Forever loop.
	while(1){
		//ReceivedData = "ASDASDAS";
		sleep_mode();

		//USART0
		if (ReceivedData0[(ReceivedDataIndex0)-1]==0x2E){
			//Function to print the RX buffer
			Serial_Print1(ReceivedData0);
			//Let's signal the end of a string.
			LF1();CR1(); //Ending characters.
			//After we used the data from buffer, clear it.
			clearBuffer0();
			//Reset the RX flag.
			rxFlag0 = 0;
		}

		//USART1
		if (ReceivedData1[(ReceivedDataIndex1)-1]==0x2E){
			//Function to print the RX buffer
			Serial_Print0(ReceivedData1);
			//Let's signal the end of a string.
			LF0();CR0(); //Ending characters.
			//After we used the data from buffer, clear it.
			clearBuffer1();
			//Reset the RX flag.
			rxFlag1 = 0;
		}


	}
}

This program is the same as above, but using the library. It simply takes data receiving from one UART and send its out the other.

Alright, that’s enough UART for awhile. I might update this when I run into bugs, which I will, I am a hack. So, use this code at your own risk of frustration.

Stuff I’d no energy to finish.

  1. Implement a circular-buffer (if I get smart enough to do it, that is).
  2. At least making the buffer size user definable. :)
Scarab

Originally posted on www.letsmakerobots.com

UPDATE: August 10th, 2014

I printed a body and added BLE. I’ll explain tomorrow after I get some rest, but the BLE was to allow me to test directed locomotion. I’ve also done some feature testing (load-sharing, charging circuit, “hunger” ADC), the board is actually a good design. Works well.

The BLE is the HM-11, itty-bitty BLE.

My goal is to test the physical and feature designs with the ATtiny84, and when Mr. Bdk6 releases his toolchain for the LPC1114, switch it as the controlling chip.

This is my version of Yahmez’ Baby Bot, the ATtiny84 Y-Baby (YB84). There are few differences from Yahmez’ version.

  1. This version uses an ATtiny84.
  2. It uses a LIR2032.
  3. It has a charge circuit built in, using the MCP73831. This circuit has load-sharing capability so the baby can “feed” without sleeping.
  4. The YB84 has two LED indicators.
  5. One pin on the YB84 monitors the battery voltage, so it can tell how “hungry” it is.

This version came about because Yahmez’ Baby Bots were so damn cool I had to copy them. Here’s the node where I asked permission and added design notes. Also, I’ve wanted to make a small, cheap, small robot to couple with my Overlord projects in hope to develop an electronic lab-rat.

Here is the BOM:

  1. 1 x LIR2032 – $.44
  2. 1 x 1uF 0402 – $.08
  3. 1 x 4.7uF 0805 – $.10
  4. 1 x B130LAW – $.41
  5. 1 x DMP1045U – $..51
  6. 2 x 3mm IR LED – ?
  7. 1 x IR RX
  8. 3 x colorful LED 0603 – $.33
  9. 2 x MBT2222A (SOT-23) – $.24
  10. 1 x 60k Resistor 0402 – $.10
  11. 1 x 100k Resistor 0402 – $.10
  12. 5 x 330 Resistor 0402 $.50
  13. 1 x MCP73831 – $.61
  14. 1 x ATtiny84 – $.1.30
  15. 1 x YB84 PCB – $1.76
  16. 2 x virbation motor – $1.95

Note, I’ve not included the IR receiver or IR transmitters in the BOM. I’ve not tested the circuit yet, or sourced cheap parts. But I’m shooting to keep them under $10.

YB84 BOM Total: $7.70

YB84 v_05

Really, there wasn’t much to developing this little guy, Yahmez had done all the work. I simply selected an Atmel uC that I felt was cheap enough and provided enough pins to accomplish what I wanted to do with the little guy. The one problem I had was with the load-sharing circuit I tried to copy from Zak Kemble.

When I went to layout the load-circuit my mind got locked on the old thought, “MOSFET diodes go against the current.” This caused me to lay the DMP1045U down backwards, which essentially shorts the battery.

This took me a bit to figure out. I apparently wasn’t the only one that made the mistake, as a comment on Zak’s blog had a fellow asking my questions for me. In the end, I got the circuit sorted out and now the little guy works as intended.

That’s about it for now. I still have lots of testing to do on the little guy.

  1. Motor placement for correct movements.
  2. Leg angling for correct gait.
  3. IR-RX circuit.
  4. IR-TX circuit.

Currently, I have a pogo-pin programming header. But it is imperative to accomplish my goals for this little guy to make him programmable via IR. This should allow me to program a swarm of these little guys without manual interaction. I know the Kilotbot projects modified the Arduino code to do this very thing. My ideal setup is to add a mobile hanging over a swarm of these guys. On this mobile would be: IR-TX, IR-RX, and a camera. The camera would be using Overlord to track these guys and the IR to communicate with them in mass.

As always, thoughts, opinions, and critiques I welcome :)

Metallurgy 101 - AVR PWM

Originally posted on www.letsmakerobots.com

This is a continuation of my Robot Metallurgy 101 Lesson Journal.

After I was able to get my motors moving using the SN754410 I became a little obessessed with understanding AVR PWM architecture. There are several tutorials that helped me a lot:

  1. Newbie Hack’s “Intro to PWM.”
  2. Newbie Hack’s “Control a Servo with PWM.”
  3. humanHardDrive’s “PWM
  4. maxEmbedded’s “AVR Timers – PWM MODE

In the end, I ripped maxEmbedded code and got my PB3 LED working in about 10 minutes. Then, I spent the next three evenings reading trying to figure out what maxEmbedded’s code was doing.

Really, it was the register and bit names that were tripping me up. Each had names like, “TCCROA1” and “OCR0A”, and so forth. Each is an initialism. This was a problem for me, I was soon lost in a jungle of intialisms, which represented abstract concepts, such as other intialisms. I felt as if I were bumbling through a George MacDonald dissertation on an orc language:

NOTE: Dear reader, I apologize if that video confused you more. Again, this is a journal so to help me remember what I learn. And I find adding a story to ridicules abstractions is necessary for me.

Alright, now that I had a little story in my head to handle the intialisms learning PWM on the AVR flowed a little easier.

Here is my reference list:

1. TCCR = Timer/Counter Control Register.

On the ATtiny1634 there are 4 control registers. One is 8-bit and the other is 16-bit. Though, this journal will stick with the Arduino standard, meaning, I’ll use my 16-bit as an 8-bit. Here are the four Timer/Counter Control Register names:

  1. TCCROA (8-bit)
  2. TCCROB (8-bit)
  3. TCCR1A (16-bit)
  4. TCCR1B (16-bit)

TCCROA (8-bit timer) and TCCROB (16-bit timer) control the PWM functions of pins.

  • TCCROA/B control pins PA5 and PA6.
  • TCCR1A/B control pins PC0 and PB3.

2. COM = Compare Output Mode

There are four bits per TCCR register that control the compare output of each pin. This is where the magic happens. If a pin is setup in compare output mode, it will only go high when the counter is equal to or higher than a number you provide. For instance,

  • Is timer greater than 100? Then go high.

This is the essence of PWM. You provide a number, in our case a number between 0-255 since it is an 8-bit counter, and if the timer is equal to or greater than your number, the pin will be HIGH. Then, the timer will continue to count up and will reset to 0 after 255 is reached. Mind you, the comparison is made every tick of the counter, so when it resets to 0 the comparison will be made and the pin will go LOW ago. Voila!

There are four COM bits in each TCCR register, two control the output of one pin.

Found in TCCR0A:

  1. COM0A0 and COM0A0 control pin PC0.
  2. COM0B0 and COM0B0 control pin PA5.

Found in TCCR1A:

  1. COM1A0 and COM1A1 control pin PB3.
  2. COM1B0 and COM1B1 control pin PA6.

Now, switching these bits can create many different types of output. But I stuck with Arduino standard.

3. WGM = Wave Form Generation (for 8-bit)

There are 3 bits that control the type of PWM we end up with. There are all sorts of wave-forms, but the main three are:

  1. Phase Correct
  2. CTC
  3. Fast PWM

(Here is an Arduino article that explains them a bit.)

The one I’ll invoke is Fast PWM,

We select this by setting WGM00 and WGM01 bits.

4. How to set the TCCR registers.

So, setting things up, the code will look something like this,

// Demonstration of PWM on an ATtiny1634.
// C. Thomas Brittain

#define F_CPU 8000000    // AVR clock frequency in Hz, used by util/delay.h
#include <avr/io.h>
#include <util/delay.h>

//Initialize PWM
void pwm_init()
{
	//This is the first PWM register, TCNT0.  It is 8 bit.  Both PIN PA5 and PA6 are set to clear on compare,
	//then set at bottom; this makes them non-inverting.  The WGM bits are set to for "Fast PWM MODE"
	//and this clears at the top, "0x00FF."
	TCCR0A = 0b10100011; // WORKS FOR OC0A, OC0B
	TCCR0B = 0b00000001; // WORKS FOR OC0A, OC0B

	//This is the second PWM register;TCNT1.  It is 8 bit.  Both PIN PB3 and PC0 are set to clear on compare,
	//then set at bottom; this makes them non-inverting.  The WGM bits are set to for "Fast PWM MODE"
	//and this clears at the top, "0x00FF."
	TCCR1A = 0b10100001;  //WORKS FOR OC1A, OC1B
	TCCR1B = 0b00001001;  //WORKS FOR OC1A, OC1B

	//This sets the PWM pins as outputs.
	DDRB |= (1<<PINB3);
	DDRA |= (1<<PINA5);
	DDRA |= (1<<PINA6);
	DDRC |= (1<<PINC0);

}

I left the assignment of the TCCR registers in a binary format. This was just easier for me, but you could as easily use bitwise operations, e.g.,

TCCR1A |= (1<<COM1A1)|(1<<WGM01)

You notice we set the COM0A1 or COM1A1 bits, but later I’ll change this so they are not set at initialization. I found if you connect the pins to the timers at the beginning, then they’ll constantly have a nominal voltage on them. This is made clearer if you have an LED on the pin. Therefore, unless you set the COM0A1 and COM1A1 bits low then the LED will never fully turn off.

Also, we have to set the data direction registers for the PWM pins to outputs.

Now, that the initialization is done, let’s look at the code I used to demonstrate PWM on the ATtiny1634.

int main()
{
	uint8_t brightness;

	// initialize timer0 in PWM mode
	pwm_init();

	//Setup several duty-cycle counters to show differential PWM channels.
	uint8_t brightness2 = 0;
	uint8_t brightness3 = 0;
	uint8_t brightness4 = 0;

	//Let's only do this 3 times before turning PWM off.
	for (int counterB = 0; counterB < 2; ++counterB){

		//The main duty PWM cycle counter will also be our loop counter. (0-255)
		for (brightness = 255; brightness > 0; --brightness)
			{
				// set the brightness as duty cycle
				brightness2 = brightness2 + 1;
				brightness3 = brightness3 + 2;
				brightness4 = brightness4 + 10;

				OCR0A = brightness;   // PCO0
				OCR0B = brightness2;  // PA5
				OCR1A = brightness3;  // PB3
				OCR1B = brightness4;  // PA6

				//Delay to make changes visible.
				_delay_ms(40);
			}

			//After 3 loops clear the PWM channels by setting COM0A1 and COM0B1 bits low.
			//If this is not done then there will be a nominal voltage on these pins due to
			//the internal pull-ups setting them as outputs.
			TCCR0A = 0b00000011; // WORKS FOR OC0A, OC0B
			TCCR1A = 0b00000011; // WORKS FOR OC0A, OC0B
		}
}

You’ll notice this is a modified “Fade” sketch from the Arduino world.

The above code provided this output,

How the magic happens in AVR is around the output comparison registers,

  1. OCR0A – controls PC0
  2. OCR0B – controls PA5
  3. OCR1A – controls PB3
  4. OCR1B – controls PA6

Basically, the OCR registers flip the pin HIGH or LOW (as setup by the TCCR) based upon the number you assign to it. If you assign OCR0A a value you of 144, it’ll be LOW (0v) for 144 clock cycles (TCNT) and HIGH (5v) for 111 clock cycles. This gives us our PWM. Booyah!

  • OCROA = 127;

This sets PC0 to approximately 2.5v. (127/255bit * 5v = ~2.5v)

  • OCR1A = 255;

This sets PB3 to 5v. (255/255bit * 5v = 5v)

Ok, here’s the tricky one,

  • OCR0A = 0;

This should set PC0 to 0v, but that’s not the case. When we set the COM registers (COM0A1, etc.) there are internal pull-up resistors connected to the corsponding pin. This results in a constant nominal voltage unless the COM register is set low again.

This can be done using the XOR operator on the TCCR register,

  • TCCRO ^= (1«COM0A0)

This should set the PC0 pin to 0v.

It’s really that simple…well, unless you want to mess with the type of PWM you are creating. Ugh.

5. ATtiny1634 analogWrite.h

After I figured out how to use PWM on the ATtiny1634, I started thinking how nice it would be to re-create the Arduino library for it.

Being able to write,

  • analogWrite(pin, strength)

had a lot of appeal to me.

I played with it a bit and ended up with the following,

#ifndef analogWrite1634
#define analogWrite1634

#include <avr/io.h>
#include <util/delay.h>

void analogWrite(int PWM_PinSelect, int duty);

// initialize PWM
void pwm_init()
{
	//Define PWM pins.
	#define PWM_PC0 1
	#define PWM_PA5 2
	#define PWM_PA6 3
	#define PWM_PB3 4

	//This is the first PWM register, TCNT0.  It is 8 bit.  Both PIN PA5 and PA6 are set to clear on compare,
	//then set at bottom; this makes them non-inverting.  The WGM bits are set to for "Fast PWM MODE"
	//and this clears at the top, "0x00FF."
	TCCR0A = 0b00000011; // WORKS FOR OC0A, OC0B
	TCCR0B = 0b00000001; // WORKS FOR OC0A, OC0B

	//This is the second PWM register;TCNT1.  It is 8 bit.  Both PIN PB3 and PC0 are set to clear on compare,
	//then set at bottom; this makes them non-inverting.  The WGM bits are set to for "Fast PWM MODE"
	//and this clears at the top, "0x00FF."
	TCCR1A = 0b00000001;  //WORKS FOR OC1A, OC1B
	TCCR1B = 0b00001001;  //WORKS FOR OC1A, OC1B

	//This sets the PWM pins as outputs.
	DDRB |= (1<<PINB3);
	DDRA |= (1<<PINA5);
	DDRA |= (1<<PINA6);
	DDRC |= (1<<PINC0);

}

void analogWrite(int PWM_PinSelect, int duty){

	//Make sure we were passed a number in-range.
	if (duty > 255) duty = 255;
	if (duty < 1) duty = 0;

	//Sets PWM for PC0
	if (PWM_PinSelect == 1){
		if (duty > 0){
			TCCR0A |= (1<<COM0A1);
			OCR0A = duty;
		}
		else {
			TCCR0A ^= (1<<COM0A1);
		}
	}

	//Sets PWM for PA5
	if (PWM_PinSelect == 2){
		if (duty > 0){
			TCCR0A |= (1<<COM0B1);
			OCR0B = duty;
		}
		else {
			TCCR0A ^= (1<<COM0B1);
		}
	}

	//Sets PWM for PA6
	if (PWM_PinSelect == 3){
		if (duty > 0){
			TCCR1A |= (1<<COM1B1);
			OCR1B = duty;
		}
		else {
			TCCR1A ^= (1<<COM1B1);
		}
	}

	//Sets PWM for PB3
	if (PWM_PinSelect == 4){
		if (duty > 0){
			TCCR1A |= (1<<COM1A1);
			OCR1A = duty;
		}
		else {
			TCCR1A	 ^= (1<<COM1A1);
		}
	}

}

#endif

A synopsis of the library,

  • Lines 1-2 and 90 make sure the library is only included once.
  • Lines 13-16 define the ATtiny1634 pins.
  • 18-28 setup the TCCR registers (notice, the pins start out off to prevent nominal voltage).
  • 41-42 makes sure our PWM value is in range.
  • 46-85 control the PWM on each pin, with an else statement to gives us a true zero voltage in the case a PWM value of 0 is passed to the function.

I saved this as 1634analogWrite.h and then wrote a sketch to use

// program to change brightness of an LED
// demonstration of PWM
//void Tiny1634_PWM(int PWM_PinSelect, int duty);

#define F_CPU 8000000    // AVR clock frequency in Hz, used by util/delay.h
#include <avr/io.h>
#include <util/delay.h>
#include "1634analogWrite.h"

int main()
{
	uint8_t brightness;

	// initialize timer0 in PWM mode
	pwm_init();
	int brightness2 = 255;
	int brightness3 = 255;
	int brightness4 = 255;
	// run forever
	while(1)
	{
		for (brightness = 255; brightness > -1; --brightness)
		{
			analogWrite(PWM_PC0, brightness);
			analogWrite(PWM_PB3, brightness2);
			analogWrite(PWM_PA5, brightness3);
			analogWrite(PWM_PA6, brightness4);

			_delay_ms(10);
			brightness2 = brightness2 - 5;
			brightness3 = brightness3 - 10;
			brightness4 = brightness4 - 15;

			if (brightness == 0)
			{
				_delay_ms(1000);
			}
			if(brightness2 < 0) brightness2 =255;
			if(brightness3 < 0) brightness3 =255;
			if(brightness4 < 0) brightness4 =255;
		}

	}
}

Ok. I’ll revisit this probably with a complete H-Bridge control library.

As always, please feel free to correct my f’ups. :)

Advanced(ish) HM-10

Originally posted on www.letsmakerobots.com

Here are some random notes on working with the HM-10.

  1. Working RX/TX LEDs
  2. How upgrade the HM-10
  3. Pseudo Star-Networking HM-10s

Working RX/TX LEDs

I spent some time trying to find a way to create RX/TX traffic LEDs for the HM-10 breakout. This might be easy for some, but it was a real thinker for me. The HM-10 is TTL, which as it was explained me, means that the line is high while idling and low to represent data. The problem here is the typical LED setup doesn’t work. Sadly, this is the setup I used in two of my fabricated boards.

Well, this stupid mistake has been staring me in the face. Especially since a few guys ordered my board and mentioned politely, “It only flashes when large amounts of data go through.”

After asking around I was told the best way to approach this problem was to use a PNP transistor. The guys at LMR pretty much gave me the solution here. The people here are brilliant. (Please don’t tell them I’m not, I want to hang with the cool-kids for a bit before they find out my mom still dresses me.)

But while LMR was helping me I found Sparkfun’s solution to the problem on one of their Xbee Explorer boards. In essence, the LEDs are wired from in between 3.3v and the TX/RX lines, this allows them to act as sinks whenever the data is coming through. As long as the LED is a green, blue or other with a 3.1v drop, then the voltage being sunk doesn’t interfere with the data.

Of course, this is risky. The CC2540 is a nifty chip, but it isn’t meant to be a high-current uC. I dug through the datasheet to see what the current sink rating of the RX/TX pins (2 & 3) were. Well…it’s not in the datasheet! But then I came across this post.

So, I checked chapter 7.3 of the CC2540 User Guide.

Well, there we go. So, I breadboarded a circuit and found it worked. But I was only brave enough to use a 1k resistor.

Eventually Brassfly helped me work through the math,

“Given that the voltage drop across the forward biased junction of a red LED is about 2 Vdc (we will call that Vf) the total current through the LED/Resistor is equal to Vsupply-Vf/R, or in this case 3.3V-2V/1000=.0013A=1.3mA….If they are bright enough then don’t worry about it. If not, you might then consider using a 470 ohm resistor (2.7mA) or even 330 ohm resistor (3.9mA).”

So, I made up a fresh version of the HM-10 breakout board (v.9.9) with this LED setup. I wired it up. And, it seems to be working.

Again, can’t use yellow or red LEDs on the RX/TX lines, since they do not create a high-enough voltage drop to signal the CC2540 low).

How upgrade the HM-10

(NOTE: You can only upgrade versions 507 or later, according to Jnhuamoa)

1. Visit the HM-10 website and learn all about the HM-10 upgrade process.

2. Download the lastest firmware version file. (Make sure your HM-10 is a CC2540, if it’s CC2541 use that file).

3. Before we proceed, here’s my bitchy disclaimer. Re-read the instructions and b_eware all ye who try to upload firmware and don’t blame me for problems, like the death of your HM-10 :P_

4. Open Realterm (or your preferred serial terminal).

5. Wire your HM-10’s serial connection as described in my earlier post.

6. You are about to cross the point of no return. Open a serial connection to the HM-10 and if you are prepared for the worst, type: “AT+SBLUP” and the module should reply, “SBLUP+OK.” Congratulations, you’ve bricked your HM-10–well, at least until the upgrade process is complete.

7. Now, CLOSE YOUR SERIAL CONNECTION in Realterm. Yes, I forgot to close the connection myself and was pissed because I thought I had bricked my HM-10 when I tried the next step. I’m a hack, hacking with a hacksaw.

8. Unzip the “HMSoft-10-2540-V522.zip” (or the latest version, respectively) into a folder. There should be several files in the folder, open HMSoft.exe

9. Now, click on the ellipsis and select “HMSoft.bin” file. Then, type the number of your com port. You don’t need to include anything but the number (e.g., COM34 becomes 34).

10. Pray (for the HM-10 this works best if to Nyarlathotep).

11. Click “Load Image.” The upload process should start pretty quick and should take approximately a minute and a half to complete. Do not remove power or screw with the wiring until you see the following:

12. Click “Ok” and open Realterm. Bring up a serial connection and type: “AT+VERS?” It should respond, “HMSoft v521.” That’s not a typo, even though we uploaded the V522 version it responds saying it is V521? You got me. But it works ok :)

Pseudo Star-Networking HM-10s

Setup up at least three units.

Unit #1 (“Master”)

  1. AT+ROLE2
  2. AT+IMME1
  3. AT+CONxxxSLAVE#1xxxx

Unit #2 (Slave #A)

  1. AT+ADDR? Write the address down. Mine replied, “OK+ADDR:883314DD8015”
  2. AT+MODE1

Unit #3 (Slave #B)

  1. AT+ADDR? Write the address down.Mine replied, “OK+ADDR:883314DD8016”

  2. AT+MODE1

Oh, one more bit. You need to wire pin 4 on the Arduino to the HM-10 Master’s reset line. Since there really isn’t anyway to reset the slave and the master at the same time. This gets us around the timeout for both, slave and master.

  • RESET<—-1k Resistor—–>D4 on Arduino

Then use the following code, changing your addresses respectively.

// Crap code for HM-10 pseudo-Networking
// By the crappy code Thomas Brittain, aka, Ladvien.

String inputString = "";         // a string to hold incoming data
boolean stringComplete = false;  // whether the string is completeString inputString = "";         // a string to hold incoming data

float time;
float oldTime;

void setup() {
// initialize serial:
Serial.begin(9600);
pinMode(4, OUTPUT);
digitalWrite(4, LOW);
}

void HM10Reset(){
  Serial.print("AT+RESET");
  delay(220);
  digitalWrite(4, HIGH);
  delay(100);
  digitalWrite(4, LOW);
  delay(150);
}

void loop() {
  // print the string when a newline arrives:
  Serial.write("AT+CON883314DD8016");
  delay(150);
  Serial.print("From first node!  Seconds ago last here: ");
  time = millis();
  Serial.println((time-oldTime)/1000);
  oldTime = millis();
  delay(250);
  HM10Reset();
  Serial.write("AT+CON883314DD8015");
  delay(150);  
  Serial.println("From second node!");
  delay(150);
  HM10Reset();
}

void serialEvent() {
  while (Serial.available()) {
  // get the new byte:
  char inChar = (char)Serial.read();
  // add it to the inputString:
  delay(50);
  inputString += inChar;
  stringComplete = true;
}

}

Not going to lie. I’m pretty dissapointed with how complicated the firmware makes it to switch between nodes. Although, I’ve only begun to play with firmware versions greater than V303.

I couldn’t do much better than about 2.84 seconds switching between nodes. This simply wont do for me. And, of course, this rate goes up with more nodes. So, a swarm of little robots controlled this way would be unmanagable.

I tried tweaking the timing of everything in the code. The HM-10 wasn’t having it. If I lowered the delay following an AT command it, the command wouldn’t take. This would often cause the nodes to become stuck (waiting for timeout, still connected, etc.) Also, the hardware reset on the HM-10 is said to be 100ms, but I’m finding it unhappy with much less than 250ms.

Anyway, if anyone else wants to carry the banner my suggestion is uping the buad rate and sticking with hardware resets, like in my ATtiny Bitsy Spider board.

Kobold

Originally posted on www.letsmakerobots.com

Kobold Files

Awhile back Sparkfun posted a new product, their MiniMoto breakout board. It breaks out the DRV8830 IC, which is a serially controlled (I2C) H-Bridge. I thought the chip was nifty. A few problems though,

  1. Sparkfun’s breakout was 25x25mm for one bridge. If I added another and then an Arduino Pro Mini it’d lose smallness.
  2. It’s $9.95
  3. It’s not on a purple board :)

So, I set out to make a robot controller with it that was smaller than a Sparkfun breakout. What I ended up with is a little bitch I refer to a Kobold.

The board is pretty straightforward. It has an ATtiny 85 that acts as an I2C Master using the SoftI2CMaster library. This allows the Tiny 85 to control two motors using only two pins, leaving three for your pleasure.

My end goal will be to build a shield for it and hook up a HM-10 to make it a little wireless tethered bot. This would bring me down to one pin, which I’m sure will be some sort of range finder or feeling sensor.

The BOM:

  1. 1 x ATtiny 85 SOIC $1.21
  2. 2 x DRV8830 MSOP-10 $5.10
  3. 2 x .33 Ohm 0402 $.86
  4. 1 x 1uF 0402
  5. 2 x 4.7k Res. 0402
  6. 1 x Kobold PCB $2.50 (for three)

Total: $9.76

The board can be programmed with an Arduino ISP:

Now, I just need to make a robot with it :)

I’m currently working on a second iteration to correct some problems. I’ll also add a few features, like my pogo-pin programming interface. The shield I have designed for it will also include a charging circuit and probably a SMD step-up circuit that should convert a LiPo to a nice 5v.

Anyway, work in progress…just thought I’d share.

If anyone is interested in this board, please wait a few iterations. I get worried I’m making blue-smoke with someone else’s money. :)

Here is the code running in the video:

//Sample Code for the Kobold Board.
#define NO_INTERRUPT 1
#define I2C_TIMEOUT 100

#define SDA_PORT PORTB
#define SDA_PIN 4
#define SCL_PORT PORTB
#define SCL_PIN 3
#include <SoftI2CMaster.h>
#include <avr/io.h>

void CPUSlowDown(int fac) {
  // slow down processor by a fac
    CLKPR = _BV(CLKPCE);
    CLKPR = _BV(CLKPS1) | _BV(CLKPS0);
}

boolean writeSpeed(byte addr, int speedx)
{
  //This should clear the fault register.
  byte regValue = 0x08;
  //Clear the fault status, in case there is one.
  if (!i2c_start(addr | I2C_WRITE)) {
    return false;
  }
  if (!i2c_write(0x01)) {  //0x01 = We want to write.
    return false;
  }
  if (!i2c_write(regValue)) { //Write the clear bye for fault register.
    return false;
  }
  i2c_stop();  //Stop transmission.

  //Let's convert the integer given us into a byte.
  regValue = (byte)abs(speedx);     //Convert 0-63 to byte value to set speed.
  if (regValue > 63) regValue = 63; // Cap the value at 63.
  regValue = regValue<<2;           // Left shift to make room for bits 1:0
  if (speedx < 0) regValue |= 0x01;  // Set bits 1:0 based on sign of input.
  else           regValue |= 0x02;   //A negative number for reverse and positive for forward.

  //Now, let's move this sucker.
  //Sets the i2c slave address
  if (!i2c_start(addr | I2C_WRITE)) {
    return false;
  }
  //0x00 = We want to write something.
  if (!i2c_write(0x00)) {
    return false;
  }
  //Writes the byte which had been converted from an integer that was passed this function.  Annnnd! The motor moves!
  if (!i2c_write(regValue)) {
    return false;
  }
  i2c_stop();
  return true;
}

boolean writeStop(byte addr)
{
  if (!i2c_start(addr | I2C_WRITE)) {
    return false;
  }
  if (!i2c_write(0x00)) {
    return false;
  }
  if (!i2c_write(0x00)) {
    return false;
  }
  i2c_stop();
  return true;
}

//------------------------------------------------------------------------------
void setup(void) {
#if I2C_CPUFREQ == (F_CPU/8)
  CPUSlowDown();
#endif
}

void loop(void){

  for (int i = 0; i <= 3; i++){
  delay(100);
  if (!writeSpeed(0xC0, 10));
  if (!writeSpeed(0xCE, 10));
  delay(1000);
  if (!writeStop(0xC0) );
  if (!writeStop(0xCE) );
  delay(1000);  
  if (!writeSpeed(0xC0, -10));
  if (!writeSpeed(0xCE, -10));
  delay(1000);  
  if (!writeStop(0xC0) );
  if (!writeStop(0xCE) );
  delay(100);  
  }
   for (int i = 0; i <= 3; i++){
       delay(100);
  if (!writeSpeed(0xC0, 14));
  if (!writeSpeed(0xCE, 34));
  delay(1000);
  if (!writeStop(0xC0) );
  if (!writeStop(0xCE) );
  delay(1000);  
  if (!writeSpeed(0xC0, -14));
  if (!writeSpeed(0xCE, -34));
  delay(1000);  
  if (!writeStop(0xC0) );
  if (!writeStop(0xCE) );
  delay(100);  
   }
}