1. 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.
    Dismiss Notice

maxsonar Ezo circuitary with atmega16

Discussion in 'AVR' started by jerry1234, Apr 19, 2013.

  1. jerry1234

    jerry1234 New Member

    Joined:
    Mar 9, 2013
    Messages:
    22
    Likes:
    0
    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...



    Code (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: Apr 20, 2013
  2. ()blivion

    ()blivion Active Member

    Joined:
    Nov 24, 2010
    Messages:
    857
    Likes:
    210
    Location:
    Level 5
    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.
     
  3. ()blivion

    ()blivion Active Member

    Joined:
    Nov 24, 2010
    Messages:
    857
    Likes:
    210
    Location:
    Level 5
    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.
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. jerry1234

    jerry1234 New Member

    Joined:
    Mar 9, 2013
    Messages:
    22
    Likes:
    0

    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...???
     
  6. ()blivion

    ()blivion Active Member

    Joined:
    Nov 24, 2010
    Messages:
    857
    Likes:
    210
    Location:
    Level 5
    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 (text):

    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.
     
  7. misterT

    misterT Well-Known Member Most Helpful Member

    Joined:
    Apr 19, 2010
    Messages:
    2,697
    Likes:
    368
    Location:
    Finland
    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: http://www.electro-tech-online.com/custompdfs/2013/04/basics2.pdf
     
    Last edited: Apr 22, 2013
  8. ()blivion

    ()blivion Active Member

    Joined:
    Nov 24, 2010
    Messages:
    857
    Likes:
    210
    Location:
    Level 5
    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.


    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.
     
  9. misterT

    misterT Well-Known Member Most Helpful Member

    Joined:
    Apr 19, 2010
    Messages:
    2,697
    Likes:
    368
    Location:
    Finland
    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.

    Code (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.


    The register value is never shifted. Only the bit-mask is created by shifting.


    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: Apr 23, 2013
  10. jerry1234

    jerry1234 New Member

    Joined:
    Mar 9, 2013
    Messages:
    22
    Likes:
    0
    Mister T will u please summarize the code in correct form....
    U got made me confuse....:p
     
  11. misterT

    misterT Well-Known Member Most Helpful Member

    Joined:
    Apr 19, 2010
    Messages:
    2,697
    Likes:
    368
    Location:
    Finland
    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: Apr 24, 2013
  12. jerry1234

    jerry1234 New Member

    Joined:
    Mar 9, 2013
    Messages:
    22
    Likes:
    0
    I have problem with sensors...
    LCD is showing the display preety well...
    But distance was not changing accordingly with the obstacle motion....:(
     
  13. misterT

    misterT Well-Known Member Most Helpful Member

    Joined:
    Apr 19, 2010
    Messages:
    2,697
    Likes:
    368
    Location:
    Finland
    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?
     
  14. jerry1234

    jerry1234 New Member

    Joined:
    Mar 9, 2013
    Messages:
    22
    Likes:
    0
    Yes yes...
    Distance value shown by sensors remain constant..no updates after first value
     
  15. jerry1234

    jerry1234 New Member

    Joined:
    Mar 9, 2013
    Messages:
    22
    Likes:
    0
    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....:)
     
  16. misterT

    misterT Well-Known Member Most Helpful Member

    Joined:
    Apr 19, 2010
    Messages:
    2,697
    Likes:
    368
    Location:
    Finland
    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?
     
  17. misterT

    misterT Well-Known Member Most Helpful Member

    Joined:
    Apr 19, 2010
    Messages:
    2,697
    Likes:
    368
    Location:
    Finland
    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.
     
  18. jerry1234

    jerry1234 New Member

    Joined:
    Mar 9, 2013
    Messages:
    22
    Likes:
    0
    First value is correct but not changing further either v restarting microcontroller...:(
     
  19. misterT

    misterT Well-Known Member Most Helpful Member

    Joined:
    Apr 19, 2010
    Messages:
    2,697
    Likes:
    368
    Location:
    Finland
    You move the obstacle further and then restart the microcontroller, but no change in the value?
     
  20. jerry1234

    jerry1234 New Member

    Joined:
    Mar 9, 2013
    Messages:
    22
    Likes:
    0
    Exactly.....No Change in values....
     
  21. misterT

    misterT Well-Known Member Most Helpful Member

    Joined:
    Apr 19, 2010
    Messages:
    2,697
    Likes:
    368
    Location:
    Finland
    Can you post what exactly is displayed on the LCD..
     

Share This Page