Can babyO and orangutan comunicate?

so, I got a baby O and an orangutan. I want to use the baby O as a subsystem of the orangutan. how can they talk with each other?
Arbel

There are a couple of different hardware interfaces built into the ATMega168 chips, logic-level serial (UART), SPI, And I2C (which for copyright reasons Atmel calls TWI). Serial is by far the easiest to use, and there’s a nice thread on serial talking between an Orangutan and a Baby Orangutan here. It’s somewhat long, but if you skim it you should find the parts you need. Keep in mind that the code developed in this thread is for one way communication from a Baby to an Orangutan, but you can swap the codes (not the LCD part of course), or blend the codes together for two-way communication (either way, make sure you keep the correct F_CPU clock speed definition with the correct device).

You can also implement just about any other kind of interface in software.

-Adam

I’ve never done that before, the thread you sent me didn’t help, I’ll tell you what I want to do, I wont the baby O will control the servos and some of the sensors, and the orangutan will control the motors and some more sensors. how can I do that? I looked at the code in the orangutan-lib but it may as well be written in chaineez! Any how, I would love a small example of a uart code with some simple explanations.
again
thanks
Arbel

Hello.

The thread Nexisnet linked has what you are asking for. Take a look at that thread starting with this post. If there are things about Nexisnet’s example that you don’t understand, perhaps you can ask some specific questions about the example.

- Ben

O.K. here is my first question - dose the babyO (the transmitter) transmit all the time and the orangutan receive all the time?

When, and for that matter what, the Baby O transmits is entirely up to you, and using the serial byte received interrupt, the Orangutan can receive data any time, and do anything else in the meantime. Take a look at the code below, which works for both transmitting and receiving, and can be compiled for either the Orangutan or the Baby O (you have to uncomment the corresponding F_CPU definition first).

//#define F_CPU 20000000//CPU clock for Baby Orangutan
//#define F_CPU 8000000//CPU clock for Orangutan
//***Uncomment ONE of the above lines for the specific device***

#define BAUD 9600//baud rate for UART
#define MYUBRR (F_CPU/16/BAUD-1)//baud rate variable for UART hardware

#include <avr/io.h>
#include <avr/interrupt.h>

unsigned volatile char dataIn,newSerCmd=0;

void USART_Init(unsigned int ubrr){//Initialize USART hardware & settings for Serial Radio
	UBRR0H=(unsigned char)(ubrr>>8);//set buad rate
	UBRR0L=(unsigned char) ubrr;
	UCSR0B=(1<<TXEN0)|(1<<RXEN0);//enable transmitter & receiver
	UCSR0B|=(1<<RXCIE0);//enable receive complete interrupt
	UCSR0C=(3<<UCSZ00);//Set frame format for 8bit with 1 stop
}

void USART_Trans(unsigned char dataOut){//Transmit a byte of data over USART
	while(!(UCSR0A&(1<<UDRE0)));//wait for transmition to complete
	UDR0=dataOut;
}

ISR(USART_RX_vect){//USART Byte reieved
	dataIn=UDR0;
	newSerCmd=1;
}

int main(){
	USART_Init(MYUBRR);//Initialize USART
	sei();//enable global interrupts

	while(1){
		if(newSerCmd){
			USART_Trans(dataIn-32);
			newSerCmd=0;
		}
	}
	return 0;
}

This code just sits around all day running through the main while loop, which for the moment consists of checking if a new serial byte has arrived, but could be anything else in the loop in the meantime.

When a new serial byte does arrive, the interrupt function ISR(USART_RX_vect) is called automatically, no matter what else is going on. In this case all it does is store the new received byte in a temporary variable (dataIn=UDR0) and set a flag variable (newSerCmd=1) for the main loop to see that a new byte has arrived (this part isn’t even really necessary, you may be able to do what you want with that received byte in the interrupt function, this is just a convenient way to let the rest of your code know that a new byte has arrived).

The main while loop sees that a new serial byte has been received, subtracts 32 from it, and sends it back out again. Why 32? In ASCII code a capital letter’s byte value is 32 less than its lower-case version, so if this code receives a lower case letter it capitalizes it and sends that back out. If it receives anything other than a lower-case letter what it sends back out won’t make any real sense, other than being 32 less.

SO, what does this mean to you? Basically that your code can send out bytes any time you want by loading them in to the USART_Trans() function. Also, it can receive serial bytes any time, and it doesn’t even need to be specifically listening or waiting for them, because the serial interrupt function will be called automatically by the AVR’s hardware. Neat Stuff!

-Adam

So I can write some thing like this?

    //#define F_CPU 20000000//CPU clock for Baby Orangutan
    //#define F_CPU 8000000//CPU clock for Orangutan
    //***Uncomment ONE of the above lines for the specific device***

    #define BAUD 9600//baud rate for UART
    #define MYUBRR (F_CPU/16/BAUD-1)//baud rate variable for UART hardware

    #include <avr/io.h>
    #include <avr/interrupt.h>

    unsigned volatile char dataIn,newSerCmd=0;

    void USART_Init(unsigned int ubrr){//Initialize USART hardware & settings for Serial Radio
       UBRR0H=(unsigned char)(ubrr>>8);//set buad rate
       UBRR0L=(unsigned char) ubrr;
       UCSR0B=(1<<TXEN0)|(1<<RXEN0);//enable transmitter & receiver
       UCSR0B|=(1<<RXCIE0);//enable receive complete interrupt
       UCSR0C=(3<<UCSZ00);//Set frame format for 8bit with 1 stop
    }

    void USART_Trans(unsigned char dataOut){//Transmit a byte of data over USART
       while(!(UCSR0A&(1<<UDRE0)));//wait for transmition to complete
       UDR0=dataOut;
    }

    ISR(USART_RX_vect){//USART Byte reieved
       dataIn=UDR0;
       newSerCmd=1;
    }

    int main(){
       USART_Init(MYUBRR);//Initialize USART
       sei();//enable global interrupts

       while(1){
          if(newSerCmd){
             lcdgotoxy(0,0);
             lcd_string(dataIn);
             newSerCmd=0;
          }
       }
       return 0;
    }

will that code display the value of dataIn that he got from the baby O on the lcd?

Arbel

Close, but there’s just a little more to it.

For the Orangutan, you’ll need to uncomment the #define F_CPU 8000000 line near the top of the code (assuming your Orangutan is running at full speed without internally dividing the clock).

If you want to use the Orangutan Lib LCD functions you’ll need to import lcd.c, lcd.h, and device.h into your AVRStudio project, and add #include “device.h” and #include “lcd.h” lines to your code (let me know if that last part makes sense).

Also the LCD_String() function is expecting a string, not just a single character, so you’ll have to store your temporary value in a character array by changing:

unsigned volatile char dataIn,newSerCmd=0;
to
unsigned volatile char newSerCmd=0;
unsigned volatile char dataIn[2]={’ ',0};

and

dataIn=UDR0;
to
dataIn[0]=UDR0;

You’ll also need to call the function lcd_init() before you try to send any characters to the LCD, and the cursor position function is lcd_gotoxy(), not lcdgotoxy().

SO, after all that the code for your Orangutan would look like this:

//#define F_CPU 20000000//CPU clock for Baby Orangutan
#define F_CPU 8000000//CPU clock for Orangutan
//***Uncomment ONE of the above lines for the specific device***

#define BAUD 9600//baud rate for UART
#define MYUBRR (F_CPU/16/BAUD-1)//baud rate variable for UART hardware

#include <avr/io.h>
#include <avr/interrupt.h>
	#include "device.h"
	#include "lcd.h"


unsigned volatile char newSerCmd=0;
unsigned volatile char dataIn[2]={' ',0};

void USART_Init(unsigned int ubrr){//Initialize USART hardware & settings for Serial Radio
   UBRR0H=(unsigned char)(ubrr>>8);//set buad rate
   UBRR0L=(unsigned char) ubrr;
   UCSR0B=(1<<TXEN0)|(1<<RXEN0);//enable transmitter & receiver
   UCSR0B|=(1<<RXCIE0);//enable receive complete interrupt
   UCSR0C=(3<<UCSZ00);//Set frame format for 8bit with 1 stop
}

void USART_Trans(unsigned char dataOut){//Transmit a byte of data over USART
   while(!(UCSR0A&(1<<UDRE0)));//wait for transmition to complete
   UDR0=dataOut;
}

ISR(USART_RX_vect){//USART Byte reieved
   dataIn[0]=UDR0;
   newSerCmd=1;
}

int main(){
   lcd_init();
   USART_Init(MYUBRR);//Initialize USART
   sei();//enable global interrupts

   while(1){
      if(newSerCmd){
         lcd_gotoxy(0,0);
         lcd_string(dataIn);
         newSerCmd=0;
      }
   }
   return 0;
}

As for connecting the two devices, I imagine you’ll have them running on the same power source, but at the very least they’ll need to have their grounds connected, and you’ll need to wire the PD1 pin (TX) on the transmitting device to the PD0 pin (RX) on the receiving device (for two way communication connect each device’s PD1 to the other’s PD0).

-Adam

hay

I tried to use the code you sent in the thread you linked me to previesly, all I did was to earase the 4 ports and to use just 1. (PC1). and it did work only that the N and n sort of flikerd and only when I touched the sensor the N was stedy when I let go of the sensor, the N flikerd beatwin N and n. I will add that for a sensor I used a simple switch.
thanks
Arbel

o.k
I solved the problem with the flikering lcd by adding a pullup resistor. my question now is how do I transmit and recive data from PORTC and D together?
Arbel

The serial protocol you’re using handles uses eight bit bytes (that is, it always sends eight bits at a time), so you can send up to eight digital pin states at once, in one byte. It’s convenient if all the pin states you want to send are on the same port, because you can just send the state of the whole port. As you know, if you wanted to transmit the state of pins PD1 PD2 and PD3 you would just do something like:

USART_Trans(PIND);

You can’t send less than eight bytes, so it’s just convenient to send along the other Port D pin states as well. If you want to send pin states from both Port C and Port D together, you have a couple of options.

The simplest way is to just send them as separate bytes, with some way of identifying them. If you wanted to know the sate of ALL the pins in Port C and Port D you could send them one right after the other, then pause for long enough that the receiving controller could measure the time and would know which byte to expect next.

If you were interested in less than seven pins of each port you could use a third, unique byte as a “new set of information” identifier. Lets say you only want the lower seven pins of Ports C and D, you could send a byte with the first bit high and then the two port states with their first bits set low.

USART_Trans(0x80);
USART_Trans(PINC&~0x08);
USART_Trans(PIND&~0x80);

So, the first byte received would be, in binary, 0b10000000, and your receiving controller would know from the first bit being high that this is a start byte, and it should expect the states of Port C and Port D to follow in that order. The &~0x80 part of the code takes a port state, and performs a bitwise and operation (&) on it with the bitwise inverse (~) of 0x80. What?

0x80=0b10000000
~0x80=0b01111111
PINC=???
PINC&~0x80=0???

Whatever the state of PINC is, what you end up with is that same state with the highest bit set to zero. That way the only byte with a high bit set to 1 is the start byte. This simple protocol is used on all of Pololu’s serial motor controller devices.

Now, if you’re interested in sending less than 8 total pin states from Ports C and D, you can combine them into one single byte and forget about the whole start byte business. Lets say, ideally that I’m interested in Pins 0-3 on Port C, and Pins 4-7 on Port D. That’s super simple:

USART_Trans((PINC&0x0F)|(PIND&0xF0));

0x0F=0b00001111, and 0xF0=0b11110000, so the operation above is taking the two port states, setting the four high bytes of the state of Port C to zero, setting the four low bytes of the state of Port D to zero, and combining them with a bitwise or operator (|). Bit wise or is exactly what it sounds like, is bit A or bit B high? So: 0b1100|0b0110=0b1110. Essentially you’re putting the first half of Port D together with the last half of Port C. You can use this technique to blend together any set of pins, so long as you’re not interested in PCx and PDx.

But what if you are, what if you need to know the state of PC3 and PD3? Add Bit shifting into the mix. You can think of the left bit shift operator (<<) and the right bit shift operator (>>) as arrows pointing in the direction you want to shift the binary bits of a number. The number before the operator is the number to be shifted, and the number following the operator is the number of bit spaces by which to shift. So, for example 63<<3=248. Really.

63=0b00111111
63<<3=0b00111111000=0b11111000=248

Since the number you’re working with is an eight bit byte, the bits shifted out of the eight available spaces disappear (no wrap around) and you’re left with 0b11111000, which is 248 in decimal. So, how to use bit shifting to your advantage? Lets say you want the low four bits of both Port C and Port D. You would write:

USART_Trans((PINC&0x0F)|(PIND<<4));

The code above shifts the state of Port D left by 4, before or-ing it with the state of Port C with its high four byte spaces blanked out. You don’t need to blank the high four bit spaces of the state of Port D because they get shifted off into oblivion, and the new placeholders for the low bit spaces are zero by default.

You can generalize these bit shifting and bitwise logic techniques to grab bits out of many different places in different numbers, but this should be plenty to get started on.

-Adam

:open_mouth: wow!!!
O.K! I will have to read this again and again and again, I am interested in some thing you wrote, about identifaing each port sent to the microcontroller, how do I do that?
Arbel

Now I’m a little confused, what (like which pins on which ports) do you want to send from one AVR to the other?

-Adam

how do I do that? or all you wrote is diffrent ways to do that?
Arbel

All I meant by that is if you’re going to send multiple bytes, it’s good to have a way for your receiving controller to identify them, and recover from mistakes.

If your transmitting controller just alternates between sending the state of Port C and Port D, ideally your receiving controller would know to expect the Port C byte, then D, then C, then D, on and on forever. But think about what would happen happens if your receiving controller missed one byte, or interpreted noise as a byte, or if you didn’t start both controllers at precisely the same time. Now the receiver will think C is D and D is C.

There’s no one way to to this, but the ones I mentioned are common examples, like sending a unique beginning byte that C or D will never be equivalent to, or pausing, or even splitting up information into more bytes and using the beginning bits as address identifiers. In general the simplest approach that will work for your situation is usually the best.

So, what are you trying to send?

-Adam

A new problem that sets me back to not programming at all!!!
my AVRISP MKII programmer is now blinkin oreng when I connect it to the computer (not to the orangutan) and AVRSTUDIO will not connect to the programmer. the connect dialog keep comming up again and again. so I can’t program nothing! ohhhhh help meee!!! :cry:
Arbel

It sounds like it might be time for a firmware reflash to try to recover your AVRISP.

With the AVRISP Plugged in, open up AVR Studio, and go to “Tools”–>“AVRISP mkII Upgrade” and follow the window instructions.

If you get an error along the way like “No AVRISP mkII in Upgrade Mode Detected” then try the procedure in the AVRISP mkII User Guide for manually entering firmware upgrade mode (on page 28). You don’t have to leave the pin-short in place during the whole upgrade, it just has to be in place while you plug the USB cable in, so I usually do it with a pair of metal tweezers.

Did that take care of it?

-Adam

works like a charme!!! thanks!
I’ll try to work some more on the options you said before. all I want to do is to be able to send all the ports on the baby O to the orangutan.
Arbel