Please Help me with this code I am having problem with this

Go To Last Post
24 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I want to read a gas sensor MQ-135 and a temperature sensor as LM335
so I am using following code

#include
#include

void UART_transmit(unsigned char data)
{
while(!(UCSRA & (1<<UDRE)));
UDR=data;
}
int main(void)
{
DDRA=0x00;
PORTA=0x00;
UCSRA=0;
UCSRB=1<<TXEN; // UART transmit enable
UCSRC=1<<URSEL | 1<<UCSZ1 | 1<<UCSZ0; // 8 data bit, a stop, none parity
UBRRH= 0x00;
UBRRL=103;
 // for 9600 baud at 16MHz
ADCSRA=0xE7;
unsigned int temp;
 unsigned char ch=0;
 while(1)
 {
 ADMUX=0x00; // Selecting Channels
 // ADC free running mode, 128 prescaling division factor
 temp=(ADC)*(48);
 temp=temp/10;
 temp=temp-2280;
 temp=temp/10;
 UART_transmit(ch+'0'); // Sending channel number for synchronization
 _delay_ms(10);
 UART_transmit(temp); // Sending temperature value
 _delay_ms(10000);

  ADMUX=0x02; // Selecting Channels
// ADC free running mode, 128 prescaling division factor
 _delay_ms(1000);
 UART_transmit(2+'0'); // Sending channel number for synchronization
 _delay_ms(10);
 UART_transmit(ADC); // Sending temperature value
 _delay_ms(10000);
 }
return 0;
}

This is giving wrong value ,

But when I read single Sensors with commenting others code they give correct value I am not able to understand the problem. Even after increasing delays as you can see _delay_ms(10000) problem remains the same.

eg:
with single temperature sensor code I have reading as
48 34 //second value is sensor value which is correct
similarly for only gas sensor code I have which is correct .
50 110
But when same code is used with other sensor it gives
48 221//
50 60//gas sensor value[/code]

Last Edited: Thu. Apr 12, 2012 - 04:15 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think I see 2 adcinits in getdata, but it seems there should be one in main to init the a/d, and there isn't one there. Go back and hit the edit button and try to line up the braces so we can see where the blocks are.

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
I think I see 2 adcinits in getdata
But adcinit does ADC = 0 which is a totally useless line of code since ADCH and ADCL are read only. Also in each loop of the while(1) (which for some reason is in adc_getdata instead of main) you are setting ADCSRA twice, using free-running mode while also changing channels, and in the first setting of ADCSRA not waiting for the conversion to complete. In other words, your code is a complete mess.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes I know its mess That two silly thing I done to overcome the problem , I think the problem is that I am not giving enough time to complete ADC its process. But then what about the delays,
And this ADC= 0 I found on some website,

Can I use multiple sensors with ADC free running if yes then how what is problem I am not getting any thing. :(

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

NOw I have changed the code according to you steve but problem still persists :(

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Can I use multiple sensors with ADC free running if yes then how what is problem I am not getting any thing.

You can but it's a real mare (the reading always lags the channel selection). Far better for multiple channel to use one-shot. Set the mux, trigger the conversion, take the reading, rinse and repeat.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Can I use multiple sensors with ADC free running if yes then how what is problem I am not getting any thing.
Free running mode is useful for one channel.
For several channels you're better off using single conversions.
In free running mode a new conversion will start as soon as the previous one is ready.
So you will have trouble to switch between channels.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I m very thankful for responses by you people,

I am a chemical Engineer and I am not used to AVR programming can anyone provide me code for doing single conversion at ADC0 and then a ADC2
Please Please If you can

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

first perhaps read the tutorials on the ADC in the tutorials forum, then you will understand what you are doing. (no offense meant)
I think that in those tutorials there even is an example to use multiple channels.
but the principle is very easy.
You set the MUX bits to the correct value, then start a measurement. now you can wait for the measurement to complete, or use interrupt to tell you the conversion is complete.
then you set the next channel ( first clear the mux bits then write the new value) and start the next conversion.....

I hope this helps in understanding...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for your response,
But I want this thing done in just 2 days so time is less very less
Now I am thinking to look for someone who can do a simple code for me.
I have given up :(
Thanks AVR freaks for all help (if possible if some one have a code please write it in comment or mail me at mailnakul@gmail.com). I can configure computer software according to given programme. :oops:

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I have given up

Why give up? You were so close with the code above and just a few lines need to change to switch from using free running. But tell you what, try this:

#include
#include

void UART_transmit(unsigned char data) {
  while(!(UCSRA & (1 << UDRE)));
  UDR=data;
}

int main(void) {
  unsigned int temp;

  UCSRB = (1 << TXEN); // UART transmit enable
  UBRRH = 0x00;
  UBRRL = 103; // for 9600 baud at 16MHz
  ADCSRA = (1 << ADEN) | (7 << ADPS0);
  while(1) {
    ADMUX=0x00; // Selecting Channels
    ADCSRA |= (1 << ADSC); // trigger conversion
    while (ADCSRA & (1 << ADSC)); // wait for it to complete
    temp = ADC * 48;
    temp = temp / 10;
    temp = temp - 2280;
    temp = temp / 10;
    UART_transmit('0'); // Sending channel number for synchronization
    UART_transmit(temp >> 8); // Sending temperature value
    UART_transmit(temp & 0xFF);
    _delay_ms(1000);

    ADMUX = 0x02; // Selecting Channels
    ADCSRA |= (1 << ADSC); // trigger conversion
    while (ADCSRA & (1 << ADSC)); // wait for it to complete
    UART_transmit('2'); // Sending channel number for synchronization
    temp = ADC;
    UART_transmit(temp >> 8); // Sending temperature value
    UART_transmit(temp & 0xFF);
    _delay_ms(1000);
  }
  return 0;
} 

I made some style/layout changes as code is easier to read and understand when it's well formatted (spaces cost nothing!). I removed lines that were pointless or had no effect. I replaced the ADCSRA=0xE7 with something that is far more readble (and does not select free running).

For both channels, after setting ADMUX I just set ADSC then wait while it remains 1. It returns to 0 when the conversion is complete at which point the 10 bit value is read into "temp". In both case I then transmit two byte in big endian (the easy to read one) order. Even in the first case if ADC=1023 then temp=263 which cannot be transmitted as 1 byte (it's over 255). In the second case you don't divide the result at all so it could easily be 1023 and again that needs the 16 bits to be split (which is what >>8 and &0xFF achieve) to send as two bytes.

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hey, thanks buddy this its a great job ,
I am getting values like
048 025 002
050 000 149
As I am very nil to computer/MCU architechture,
What mathematics should I do to real the actual value,
My computer software can read individual bytes,

Now what does 025 002 means whats the logic is this means 25.2 or something like that,
Sorry If my question is stupid

ALso do you have any idea to calculate CO2 conc fromMQ 135.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

HEy I got the concept of reading the data thanks a lot for all help and
Do tell tell about getting the concentration of CO2 from MQ 135 if you know :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

By the time I have also developed a trick to read multiple sensor from "ADC free running mode " look at the code It first reads 25 times from one sensor and next 25 times from other, Just a fun code for one who dont want to got hrough datasheets of ATMEGA32:

#include
#include
void UART_transmit(unsigned char data)
{
while(!(UCSRA & (1<<UDRE)));
UDR=data;
}
void adc_getdata(void)
{
unsigned int temp;
unsigned int ppm;
unsigned char ch=0;
int i=0;
ADMUX=0x00+ch;
ADCSRA=0xE7;
while(i<25)
{
  // Selecting Channels
 // ADC free running mode, 128 prescaling division
temp=(ADC)*(48);
temp=temp/10;
temp=temp-2280;
temp=temp/10;
_delay_us(1000);
UART_transmit(ch+'0'); // Sending channel number for
_delay_ms(10);
UART_transmit(temp); // Sending temperature value
_delay_ms(1000);
i++;
}
i=0;
ch = 2;
ADMUX=0x00+ch;
ADCSRA=0xE7; 
while(i<25)
{
ppm=ADC;
_delay_us(1000);
UART_transmit(ch+'0'); // Sending channel number for
_delay_ms(10);
UART_transmit(ppm); // Sending temperature value
_delay_ms(1000);
i++;
}

}

int main(void)
{
DDRA=0x00;
PORTA=0x00;
UCSRA=0;
UCSRB=1<<TXEN; // UART transmit enable
UCSRC=1<<URSEL | 1<<UCSZ1 | 1<<UCSZ0; // 8 data bit, a stop, none
UBRRH=0;
UBRRL=51; // for 4800 baud at 16MHz
while(1)
{
adc_getdata();	
}
return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That sounds like a fun game... guess how the microcontroller works without reading the datasheet. Hey! Maybe you can just ask a question on a forum about how the microcontroller works, and some retired guy with nothing to do will read the datasheet and type a paragraph from it into the reply! Yeah! That's the ticket!

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

not reading datasheet in sense that if you know code
for "adc free running",
and you dont want to go in datasheet to have single conversion mode.
That I was saying.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Can any explain big endian format I am confused again
:( how to read it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm confused both by your posts here and you PM's. Above you said:

Quote:

HEy I got the concept of reading the data thanks a lot for all help a

but are you saying you haven't actually got it? Anyway just to be clear. If you receive (as numbers):

048 025 002
050 000 149 

Then you already know that the data starts with '0' or '2' and if you look those up in an ASCII table you will find they have hex codes 0x30 and 0x32 which in decimal are 48 and 50. It's clear therefore that the 048 and 050 you see in the above are the codes for '0' and '2' being reported in decimal (how horrid - I much prefer hex - but then I'm a programmer). So now we know that the data of the channel 0 reading is "025 002" and the channel 2 reading is 000 149. Now I'd been expecting you to be reading this in hex in which case you would have seen

30 19 02
32 00 95

That would have been easy to read because I deliberately sent the bytes in "big endian" order which means the most significant number comes first so the channel 0 (30) reading could be read as 0x1902 and the channel 2 (32) reading as 0x0095. However your terminal is outputting in decimal so to combine the reading you have to do a little maths. The first byte is 256 times more significant than the second so the channel 0 (48) reading is (25*256) + 02 and the channel 2 (50) reading is (0*256) + 149. Therefore the first reading is 6,402 and the second is just 149.

Hope that helps.

But I would see if your terminal could be persuaded to display hex or simply switch to sending ASCII in the first place with something like:

UART_transmit(ch + '0');
char buffer[4];
itoa(temp, buffer, 10);
for(i=0; i

in which case you can set your terminal back to normal ASCII display mode. Human beings much prefer talking in ASCII anyway!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hey Clawson,
Thank you Very much sir, For your time
You have provided a Knowledge that I will always keep With me,
Millions of thanks to you Now I am ready with my project just because of you. :) :) :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Good thread title might be 'sending multi byte numbers across serial'

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hi ..
i am getting analog values from mq135 but i dont know how to convert those values in ppm.so pls help me.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hi ..
i want to calibrate NH3 using MQ135.
i am getting analog values from mq135 but i dont know how to convert those values in ppm.so pls help me.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why have you posted a statement in the projects area that infers you have already done this project when clearly you haven't. Please delete your "project".

AND .... why have you added your topic to another that has NOTHING to do with yours? You are supposed to start a "new Topic" using the button in the top left corner. And please use a title that identifies your actual question. Such as "Converting mq135 values to ppm"

Thanks,

Ross McKenzie ValuSoft Melbourne Australia

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

and an additional question, why are you afraid to read the datasheet????
I guess the OP did that and found a solution to his problem....