Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

maxsonar Ezo circuitary with atmega16

Status
Not open for further replies.

jerry1234

New Member
asdasd.jpg

as circuit image is attached and for the circuit the is also attach...
i hav a problem in this module...
problem is sensor donot showing its distance calculation on lcd...
can anybody plzzz tell me how i get solve this problem.....
its v urgent plzzz help me.....
the program is...



C:
/*****************************
EZO sensors test code
******************************
Program by : Manu krishnan
version : 1.0.0.0 (beta)
Assembled in : winavr
core : mega 16 (16k)
fuse : 11.0592Mhz interna
AVR Studio : 4.15.623
GUI Version : 4, 15, 0, 623
AVR Simulator: 1, 0, 2, 1
ATMEGA16 247
date : 25 March 2013 20.44
*******************************/

/*******************************
Preprovcessor Directive
*******************************/
#define F_CPU 11059200UL
#include<avr/io.h>
#include<util/delay.h>
#include<avr/interrupt.h>
/******************************/
/*******************************
LCD definitions
*******************************/
#define ctrl PORTC //dataport
#define en PC3 //enable signal
#define rs PC2 //resister select signal
//MACROS
#define output_low(port,pin) port &= ~(1<<pin)
#define output_high(port,pin) port |= (1<<pin)
#define set_input(portdir,pin) portdir &= ~(1<<pin)
#define set_output(portdir,pin) portdir |= (1<<pin)
/*******************************
uart definitions
*******************************/

#define USART_BAUDRATE 4800
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
/*******************************
Function definitions
*******************************/
void convert(unsigned int value,unsigned int numb);
void dis_data(char data_value);
void dis_cmd(char cmd_value);
/////////////////////////////////
void lcdcmd(char cmdout);
void lcddata(char dataout);
void lcd_write_string(unsigned char *str);
void lcd_init();
void to_line(char line,char pos);
void clear();
void convert(unsigned int value,unsigned int numb);
////////////////////////////////
void setup();
////////////////////////////////
void usart_init();
void usart_putch(unsigned char send);
unsigned int usart_getch();
void uart_string(unsigned char *str);
////////////////////////////////////
char txt[];
char a;
volatile unsigned char serial,i;
volatile unsigned char data[3];
/*******************************
Main Function Start
*******************************/
int main()
{

setup();
to_line(1,0);
lcd_write_string("Distance:-");
while(1)//infinite loop
{
to_line(2,0);
for(a=0;a<=2;a++)
{
data[a]= usart_getch();
}

for(a=0;a<=2;a++)
{
dis_data(data[a]);
}
lcd_write_string("c.m.");

}
}
/*******************************
End main
*******************************/
void setup()
{

DDRA=0x00;
DDRC=0xff;
// PORTD=0xff;
lcd_init();
usart_init();
uart_string("test");
// t2_fastpwm_init();

}
/*******************************
Class LCD 4 bit for 4 bit lcd
interface
*******************************/
void lcd_init() // fuction for intialize
{
dis_cmd(0x02); // to initialize LCD in 4-bit mode.
dis_cmd(0x28); //to initialize LCD in 2 lines, 5X7 dots and 4bit mode.
dis_cmd(0x0C);
dis_cmd(0x06);
dis_cmd(0x80);
}

void dis_cmd(char cmd_value)
{
char cmd_value1;
cmd_value1 = cmd_value & 0xF0; //mask lower nibble because PA4-PA7 pins are used.
lcdcmd(cmd_value1); // send to LCD
cmd_value1 = ((cmd_value<<4) & 0xF0); //shift 4-bit and mask
lcdcmd(cmd_value1); // send to LCD
}

void to_line(char line,char pos)
{
if(line ==1)
{
dis_cmd(0x80 + pos);
}
else
{
dis_cmd(0xC0+pos);
}
}
void clear()
{
to_line(1,0);
lcd_write_string(" ");
to_line(2,0);
lcd_write_string(" ");
}

void dis_data(char data_value)
{
char data_value1;
data_value1=data_value&0xF0;
lcddata(data_value1);
data_value1=((data_value<<4)&0xF0);
lcddata(data_value1);
}

void lcdcmd(char cmdout)
{
ctrl=cmdout;
ctrl&=~(1<<rs);
ctrl|=(1<<en);
_delay_ms(1);
ctrl&=~(1<<en);
}

void lcddata(char dataout)
{
ctrl=dataout;
ctrl|=(1<<rs);
ctrl|=(1<<en);
_delay_ms(1);
ctrl&=~(1<<en);
}

void lcd_write_string(unsigned char *str) //take address vaue of the string in pionter *str
{
int i=0;
while(str[i]!='\0') // loop will go on till the NULL charaters is soon in string
{
dis_data(str[i]); // sending data on CD byte by byte
i++;
}
return;
}
/*******************************
uart thingies
*******************************/
void usart_init()
{
UCSRB |= (1<<RXCIE) | (1 << RXEN) | (1 << TXEN); // Turn on the transmission reception ..
// circuitry and receiver interrupt
UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); // Use 8-bit character sizes
UBRRL = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value..
// into the low byte of the UBRR register
UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value..
// into the high byte of the UBRR register
}
unsigned int usart_getch()
{
while ((UCSRA & (1 << RXC)) == 0);
// Do nothing until data have been received and is ready to be read from UDR
return(UDR); // return the byte

}
void usart_putch(unsigned char send)
{
while ((UCSRA & (1 << UDRE)) == 0); // Do nothing until UDR is ready..
// for more data to be written to it
UDR = send; // Send the byte
}
void uart_string(unsigned char *str) //take address vaue of the string in pionter *str
{
int i=0;
while(str[i]!='\0') // loop will go on till the NULL charaters is soon in string
{
usart_putch(str[i]); // sending data on CD byte by byte
i++;
}
return;
}
 
Last edited by a moderator:
You shouldn't multy post, it's highly annoying, against the rules, and won't solve your problem any faster than picking a category and just sticking with it.

Flagged for removal. Use the microcontroller section of the form instead.
 
Power up *JUST* the sonar module and point it at a flat surface, then measure the voltage at the analog output with a digital multimeter. Do this a few times, each time with the module a different distance from the flat surface and note the voltage each time. This will tell you if the module is working properly, I suspect that it is.

You can move on to working at other possible problems after you have done this.
 
i had check this with multimeter...
Yes sonar is showing different readings....
but when i attach this sonar wth atmega 16 and with programming it soesnt showing any response that was shown by sonar in multimeter.......
Y...???
 
Unfortunately, I'm probably not going to be very helpful. I'm not very strong with C (when compared to the gurus). I don't use sonar modules, I would make them myself. And I don't know a lot about Atmel micros, I use PIC and ASM mostly.

Anyway, if in the above test the sonar module is giving you different voltages with changing distance, then it's probably working fine. The next step would be to check if the LCD works, then the Atmel Microcontroller. I would bet they are all good, and that it is the code that is giving you all your problems.

Did you just copy/paste the code from somewhere without modifications? Because, if you did, then you probably need to do some slight tweaks to it. It doesn't really look like you did, as I see a few little mistakes and points of interest, that I will mention now.


============= Observations =============
Your baud rate for the USART is probably wrong. I assume you are using the "LV-MaxSonar®-EZ0", in which case the baud setting should be 9600, not 4800.

Why is the clock speed set up to "11.0592Mhz internal" Is that even possible? Are you actually using a crystal with that speed printed on it, not an internal oscillator? This just seams like it is set up wrong to me. You shouldn't be able to make the internal oscillator odd speeds like this. It should be an even large number, like 12000000 or 8000000. Telling the rest of the software "this is what the speed is" when it's not true can definitely screw with your USART timings, and make it not get any data from the sonar module.

Why are you sending the string "test" out the USART? Do you have a terminal or something attached to the TX pin on the ATmega? In the schematic, you don't have it hooked up to the sonar module, so that's not the problem. Just keep in mind that (according to the datasheet) if you mess with the RX pin of the sonar module it will stop range finding. Make sure the RX pin of the sonar module is left unconnected, or held high.

The sonar module sends out the ASCII letter "R", the ASCII numerals for the distance (up to 255 inches) then a carriage return. Now maybe I missed it, but I don't see anything in your code to handle/strip the extra data. Are you doing this properly or not?

Now I could be entirely mistaken, but the way you are setting and clearing bits looks very odd, if not completely wrong. It looks like you are setting bits with the left shift operator "<<" ??? For example, in the function "lcddata()" you are doing "ctrl |= (1<<rs);" Which to me evaluates as "ctrl equals the bitwise OR of (bitwise left shift of "1" by rs)" I don't know of any reason to shift a single bit, unless you really want the carry bit to get involved. Nor do I know why you would try to left shift a constant numeral. In fact, trying to do that last part should give you a compiler error, so maybe this bit of code is just tricky and blowing my mind and it all works perfectly. But if it were me, instead of doing it the way you have it, I think I would simply be doing "rs = 1;" or "rs = 0;" to set the LCD up for either commands or text data. And do similar for the "en" pin also. The code should look something like this.

Code:
void lcdcmd(char cmdout)
    {
    ctrl=cmdout;  // Move command data to the output port.
    rs = 0;      // Select the "command" register
    en = 1;     
    _delay_ms(1);  // Clock out the data.
    en = 0;
    }

void lcddata(char dataout)
    {
    ctrl=dataout;  // Move text data to the output port.
    rs = 1;      // Select the "text" register
    en = 1;
    _delay_ms(1);  // Clock out the data.
    en = 0;
    }

Anyway, that's all I can help you right now. Again these are just observations, I could be wrong. But looks like it's all the help your going to get before Tuesday. Hope it's enough.
 
Now I could be entirely mistaken, but the way you are setting and clearing bits looks very odd, if not completely wrong. It looks like you are setting bits with the left shift operator "<<" ??? For example, in the function "lcddata()" you are doing "ctrl |= (1<<rs);" Which to me evaluates as "ctrl equals the bitwise OR of (bitwise left shift of "1" by rs)" I don't know of any reason to shift a single bit, unless you really want the carry bit to get involved. Nor do I know why you would try to left shift a constant numeral. In fact, trying to do that last part should give you a compiler error, so maybe this bit of code is just tricky and blowing my mind and it all works perfectly. But if it were me, instead of doing it the way you have it, I think I would simply be doing "rs = 1;" or "rs = 0;" to set the LCD up for either commands or text data. And do similar for the "en" pin also. The code should look something like this.

In above code the "rs" is the bit number that he wants to set in register (or byte) ctrl. I break it down for you:

This line of code sets a bit number 5 in register ctrl:
ctrl |= (1<<5);

The bit shift creates a bit mask:
(1<<5) = 0b00100000;

This happens because:
1 = 0b00000001; And when that is shifted to the left, then the "one" is at the right position.

That mask is then bitwise OR'ed with the register value.. though setting the bit number 5.
ctrl = ctrl | 0b00100000;


It can get litte confusing. Many times I see people trying to clear a bit with:
ctrl |= (0<<5);

But, that does not work because a zero shifted is still a zero. And bitwise OR with zero does nothing.
Clearing a bit happens like this:
ctrl &= ~(1<<5);

I leave it to you figure out how that works if you are interested. It is not hard if you go through it step by step.

More bit-operation wizardry: https://www.electro-tech-online.com/custompdfs/2013/04/basics2.pdf
 
Last edited:
Thanks for explaining that for us all MisterT, makes sense now.

If I'm understanding this right though, the code in question would compile into several shifting instructions or a loop of shifting, then a byte wide boolean instruction to apply the newly created mask to the register under work. Is this thinking correct? If so, would it not be more efficient to just use whatever code will compile into a single instruction, an instruction which simply sets/clears the bit of interest directly? Seams to me no matter how good the compiler is, with the code in question it would have to generate a few L-shift instructions (and possibly a NOT) then an OR or AND instruction to set/clear the bit. Which is a whole lot more complex than just doing the wanted computation with one single "bit_set X" or "bit_clear X" like instruction. (Taking into account possible RMW issues if applicable of course.)

Also, isn't there going to be potential issues with shifting bits around in a port register in particular? That's an output register after all, it should be directly connected to pins, pins that we may not want to mess with. Seams like shifting bits in such a register, no matter how fast, is still going to make the devices pins go logic high for a few nano seconds or more. I would think this could cause undefined behaviour, possibly leading to glitches, noise, buss contention, excess power usage, and so forth. This again makes me prefer to just set the bit with one single instruction.


MisterT said:
Clearing a bit happens like this:
ctrl &= ~(1<<5);

I leave it to you figure out how that works if you are interested. It is not hard if you go through it step by step.
Yeah, it's fairly easy (now that I know what the heck is going on in the parentheses...)

First, create the bit mask by shifting "0b00000001" to the left 5 times, making "0b00100000"
Second, invert the mask with the NOT operator, to make "0b11011111".
Third, AND the mask to "ctrl", clearing only the sixth/fifth bit.

The above works because ANDing with mask bits that are 1 doesn't alter any working register bits, but ANDing with 0 always clears them, so the above operation is selectively clearing bits, and the previously discussed operation is selectively setting them.

In the end, the technique of bit masking is far more useful if you have several bits in a register you want to set/clear/flip/test at once, as opposed to testing just one single bit. Most architectures (well, most that I have seen) have single instructions that are tailor made for doing all those things for single bits already. In PIC ASM, boolean operations involving a single bit are really just a single cycle bit manipulation instruction. I can't imagine it would be different for AVR. So if the OP's objective is just to set/clear single bits like he is doing for an LCD control line, and RMW is not going to be a problem, then I still think using source that compiles into "set bit X" or "clear bit X" is the most efficient, fast, dense, and straightforward way to do it.

Anyway, I'm looking to get a trial or free version of a C compiler for PIC so I can see some disassembly of what all this source compiles into, to better examine my hypothesis. I'm certainly not trying to pick a fight or claiming your wrong or anything, I simply suspect that if the source works as you are describing it, (which it almost certainly does, as you know what you're doing) then it is quite inefficient on most architectures and should probably be avoided.

But such things are probably best left to a different thread.
 
Thanks for explaining that for us all MisterT, makes sense now.

If I'm understanding this right though, the code in question would compile into several shifting instructions or a loop of shifting, then a byte wide boolean instruction to apply the newly created mask to the register under work. Is this thinking correct?

Usually no, because the bit number is usually a constant that is defined by user or is defined in the specific chips IO library. Using constants means that the pre-compiler can optimize the code (pre-calculate the mask) etc.

C:
#include <avr/io.h> /* Register defines */
#define BIT_NUMBER   5

REGISTER |= (1<<BIT_NUMBER);

/* The mask is calculated by the precompiler, so this is what the actual compiler sees */
REGISTER |= 0b00100000;  // This is usually compiled into singe instruction
Of course if you use genuine variables etc. then the precompiler and compiler can't optimize the code that much and the worst case scenario happens.


Also, isn't there going to be potential issues with shifting bits around in a port register in particular?
The register value is never shifted. Only the bit-mask is created by shifting.


So if the OP's objective is just to set/clear single bits like he is doing for an LCD control line, and RMW is not going to be a problem, then I still think using source that compiles into "set bit X" or "clear bit X" is the most efficient, fast, dense, and straightforward way to do it.
Difficult to say how good the OP's code is, because I can't see how the "ctrl" and "rs" are defined. If ctrl is a register and rs is just a literal constant, then his "bit setting"-code should compile into single instruction.


EDIT: Ok.. I found the definitions.. first lines of the code, d'oh. :)

#define ctrl PORTC //dataport
#define en PC3 //enable signal
#define rs PC2 //resister select signal

So they are just a port register and a pin number.. so the piece of code we are talking about should compile into single instruction.
 
Last edited:
Mister T will u please summarize the code in correct form....
U got made me confuse....:p

You can pretty much ignore my previous posts. Those were replies to ()blivion (sorry about that). I have not read your code.

What is the problem you are having. Do you have problem with the LCD or with the sensor?

I mean, have you tried to write something simple to the LCD to check that it works. Comment out all the sensor related code and try something simple like: lcd_write_string("Hello LCD!");
And see if the LCD works. That way you can be sure that your LCD is working. After.. and only after.. the LCD works, you can start testing the USART communication.. and after that the sensor. You really need to test and write your code step by step.

Do not send anything to the USART! Don't even connect the usart transmit pin to the sensor!
 
Last edited:
I have problem with sensors...
LCD is showing the display preety well...
But distance was not changing accordingly with the obstacle motion....:(
 
But distance was not changing accordingly with the obstacle motion....:(

So the distance value shown in LCD is constant?
Is the first value correct or just some random value?
Is the value always the same value?
Does the distance value change if you restart the microcontroller and the distance to obstacle is different? I mean, does the sensor only measure once and then stop updating the distance value?
 
Mister T please tell can i interface these sensors via adc channel of microcontroller ATmega16,because according to the pin discription of these sensor PIN5 which is labelled as AN(analog) which continuously giving the voltage as obstacle move nearer or far from the sensor....:)
 
Please.. You are not giving enough information. It is impossible to guess what might be wrong.

Does the first value change if you move the obstacle and restart the microcontroller? Is the first value correct?
 
Mister T please tell can i interface these sensors via adc channel of microcontroller ATmega16,because according to the pin discription of these sensor PIN5 which is labelled as AN(analog) which continuously giving the voltage as obstacle move nearer or far from the sensor....:)

I think you should keep to the UART communication. Of course you can change to the analog if you want, but I would keep the UART.
 
First value is correct but not changing further either v restarting microcontroller...:(

You move the obstacle further and then restart the microcontroller, but no change in the value?
 
Can you post what exactly is displayed on the LCD..
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top