Sending 32 bit data over USART: Garbage data received!

Go To Last Post
67 posts / 0 new

Pages

Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello all! My apologies if I am not posting in the correct place, or if this thread is a repeat.

 

My problem is garbage data on tera term.

 

I'm working on an arduino uno r3 (atmega328p). I have been working my way back through the arduino starter kit doing the projects in atmel studio with true embedded c, after having done most of the projects in the arduino IDE. I am on project 3, the 'Love-O-Meter.' This project is an external temperature sensor, from which it calculates the temperature in degrees celsius, updates serial output with the temperature and makes 0-3 LEDs light up depending on the temperature.

 

The part that's giving me trouble is the serial output. The trickiness stems from the fact that the degrees celcius is a signed 32 bit number (float), but the serial line is designed to transmit 8 bit numbers. After a fair amount of looking around, I came across a solution for transmitting the data by using the union keyword so that there is an array of 4 1 byte chars occupying the same space in memory as the 32 bit floating point number, and then transmitting each of the chars one at a time. Without further ado, my code:

 

#include <avr/io.h>	

#define F_CPU 8000000UL
#define FOSC 16000000UL
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE FOSC/16/USART_BAUDRATE - 1	

int main(void) {	

	// Set up analog input...
	ADMUX |= (1 << REFS0);
	ADCSRA |= ((1 << ADATE) | (1 << ADSC) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0) | (1 << ADEN));

	// Set up timer...
	TCCR1B |= ((1 << CS10) | (1 << CS02));

	// Set up Serial communication...
	UBRR0H = ((BAUD_PRESCALE) >> 8);
	UBRR0L = BAUD_PRESCALE;
	UCSR0B |= ((1 << TXEN0) | (1 << RXEN0));
	UCSR0C |= ((1 << UCSZ01) | (1 << UCSZ00));

	// Configure GPI/O pins 2, 3, and 4 as OUTPUT.
	DDRD |= ((1 << DDD4) | (1 << DDD3) | (1 << DDD2));

	// Declare some variables
	uint16_t tempReading;
	float volts;
	union temperature_t {
		float degreesCelcius_f;
		char degreeesCelcius_c[4];
	} temperature;

	// Main While Loop
	/* Once per second...
	 *		... Calculate the temperature.
	 *		... Update Serial communication
	 *		... Control 3 LEDs
	 */
    while (1) {
                // Check to see if one second has passed.
		if (TCNT1 >= 31249) {
			// Reset the timer to 0.
			TCNT1 = 0;
			// Calculate the temperature in celcius. -50 <= degreesCelcius <= 450
			tempReading = ((ADCH << 8) | ADCL);
			volts = (tempReading * 5.0) / 1024;
			temperature.degreesCelcius_f = (volts - 0.5) * 100;
			// Update Serial communications with the degreesCelcius...
			for (int i = 0; i < 4; i++) {
				while ( !(UCSR0A & (1 << UDRE0)) ) { }
				UDR0 = temperature.degreeesCelcius_c[i];
			}
			// Turn LEDs ON/OFF to visually represent degreesCelcius.
			if (temperature.degreesCelcius_f < 15) {
				PORTD = 0x00;
			} else if (temperature.degreesCelcius_f < 25) {
				PORTD = ((1 << PORTD3) | (1 << PORTD2));
			} else {
				PORTD = ((1 << PORTD4) | (1 << PORTD3) | (1 << PORTD2));
			}
		}
    }
}

I think the problem is on the receiving end. I am plugging the arduino board into my laptop via a USB cable and monitoring the serial data via tera term. Tera term setting are correct: 9600BAUD, 8 bit data, 1 stop bit and no parity... I must admit that after doing a few searches for combining the four bytes into a 32 bit number, I still have no real idea of how to do it...? Any help would be much appreciated.

 

By the way, I am aware that there is a internal temperature sensor on the atmega328p and my next project will be to reimplement the 'Love-O-Meter' with this internal sensor.

Thomas Brannan | thomascbrannan@gmail.com

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

I don't understand the way you read ADC and update serial com.
Is it that simple in Arduino?
.
MG

I don't know why I'm still doing this hobby

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

First up, why use a float to represent temperature? You only have a fixed range and precision so you can most likely represent all values in a byte.
The other problem is you have four bytes. How do you know that receiving side receives those four bytes correctly and not the last two bytes from the previous transmission and two bytes from the current transmission.
What displays the recovered float value? A PC? If so, the byte order to represent a float value is different on a PC. This is known as 'endianess'.
The simple solution is to use printf/sprintf to convert the binary value into a human readable ascii string. Then you can read the value on the terminal program. If you want a program on the PC to interpret the string, most languages have functions to do this.

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

Now i understand your conundrum. I would've just used the Arduino functions myself.......

Anyways, have a read of this:
http://www.avrfreaks.net/forum/how-use-printf-uart

And break your code up into functions. It makes it easier to debug.

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

A solution would be to use 1/10 degree as units (displaying float eat 2 K extra flesh ; better to keep Arduino).  Loving people temperatures (in Celsius) cannot be higher than 45C == 450 1/10C, AFAIK  (and one cannot survive temperatures above 70 C) : they can be represented on 16 bits ; in avrlibc, itoa http://www.atmel.com/webdoc/avrlibcreferencemanual/group__avr__stdlib_1gaa571de9e773dde59b0550a5ca4bd2f00.html converts a 16 bit integer into a null terminated string, ready to be sent to your PC (your choice of teraterm is, IMO, a good one).

 

Another thing makes me crazy :


#define F_CPU 8000000UL
#define FOSC 16000000UL

BTW, you can send at highre rates than 9600 bauds (ahnd you should not send raw data: their ASCII conversion is human readable, though it is aa little slower to transmit : that is why I said baud rates could be much highre)

Last Edited: Wed. Jul 19, 2017 - 06:17 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

dbrion0606 wrote:
you should not send raw data

There is nothing wrong with sending "raw" data as such.

 

Many protocols send raw data.

 

Obviously, though, it is not going to be human-readable; eg, on a terminal.

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2

If you are hoping to see it on a terminal then use dtostrf() or sprintf() to convert the binary float to human readable then send the generated string.

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

a)I know that raw data can be readable (Bray Trerminal can display their hex value with a menu mouse click; TeraTerm has an option in this purpose ).

b) for debugging pourpose, or for display purpose, it is useless

c) what was the topic/the context? (if OP wanted to send data as fast as possible, I would have written : "you should send raw data" . I did write the opposite, because I was aware of the topic....)

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

dbrion0606 wrote:
a)I know that raw data can be readable (Bray Trerminal can display their hex value with a menu mouse click; TeraTerm has an option in this purpose ).
Define "readable"! Even if you get Realterm/Bray/whatever to show you the four hex bytes it is going to be in IEEE754 format isn't it? It takes a VERY special human who can make sense of IEEE754 bytes just by looking at them !!

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

Well, 33 years ago, I had to read float values in hexa (never occured again; took time to understand that). My eyes became normal, after this very unpleasant issue.

I recommended (eats less ressources) using integers instead of floats to display temperatures...

 

It was a concession (it was ,not even ironical ... should have been very sarcastic w/r topic)  to awneil post (IMO, OPs eyes do not need to be that special to read temperatures in a convenient basis)

Last Edited: Wed. Jul 19, 2017 - 08:31 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Teraterm can be configured to receive raw values https://ttssh2.osdn.jp/manual/en/setup/teraterm-term.html

 

Displaying all received characters

This is not comfortabe at all, anyway (but it is a reason I chose Teraterm ; did not know Bray Terminal was easier in this respect)

There remain two easy to read **and* to understand solutions :

dtostr or sprintf ( formats floats, in the general case : if one has many float computations, this is the best solution ) -clawsons post no 7-

itoa (assumes values are displayed in 1/10 C, less easy to read, but uses less resources than floats; it needs  more care in conversions)

 

 

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

I am working on redirecting STD I/O to USART so I can send text to my terminal with printf(). I will report back in a bit with my new code!

Thomas Brannan | thomascbrannan@gmail.com

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

One more thing...

 

tempReading = ((ADCH << 8) | ADCL);

should just be done as...

tempReading = ADC;

The compiler knows how to read 16 bit registers correctly!

 

Jim

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274

 

 

 

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

The OP's problem is in the temperature union of float / char array.

Follow Clawsons advise in  post #7.

The goal is to convert your number to a string of text and then send that string of text over the uart.

 

Floats are a pretty complicated number format:

https://en.wikipedia.org/wiki/Si...

 

It might be a good idea to follow the (presumably working) code you had for the Arduino platform into the library functions and then copy/paste that code in your own program.

Reading code written by others is a good learning experience.

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

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

EDIT: I answered my own question! See the next post.

 

So, I've been acting on some of the advice posted in this thread. And also doing a little research of my own. I'm pretty sure the code I've come up with works, but I think I need to set some linker options so that the printf() function will actually print a floating point number. I think those options are '-Wl,-u,vfprintf -lprintf_flt', but I'm not sure where I actually put the options in? I found a page about linker options from the official atmel studio 7 documentation, but it didn't seem to say how you actually open the interface where you enter the options.

 

Here's my code:

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

#define F_CPU 8000000UL // Speed of ATmega328P is 8E6Hz
#define FOSC 16000000UL	// Clock speed.
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE FOSC/16/USART_BAUDRATE - 1	

int uart_putchar(char c, FILE *stream) {
    if (c == '\n') {
        uart_putchar('\r', stream);
    }
    loop_until_bit_is_set(UCSR0A, UDRE0);
    UDR0 = c;
	return 0;
}

int main(void) {	

	// Set up analog input...
	ADMUX |= _BV(REFS0);
	ADCSRA |= (_BV(ADATE) | _BV(ADSC) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0) | _BV(ADEN));

	// Set up timer...
	TCCR1B |= (_BV(CS10) | _BV(CS02));

	// Set up Serial communication...
	UBRR0H = ((BAUD_PRESCALE) >> 8);
	UBRR0L = BAUD_PRESCALE;
	UCSR0B |= (_BV(TXEN0) | _BV(RXEN0));
	UCSR0C |= (_BV(UCSZ01) | _BV(UCSZ00));

	// Redirect STDOUT to USART
	/*FILE* uart_output = */ fdevopen(&uart_putchar, NULL);

	// Configure GPI/O pins 2, 3, and 4 as OUTPUT.
	DDRD |= (_BV(DDD4) | _BV(DDD3) | _BV(DDD2));

	// Declare some variables
	uint16_t tempReading;
	float volts;
	float degreesCelcius;

	// Main While Loop
	/* Once per second...
	 *		... Calculate the temperature.
	 *		... Update Serial communication
	 *		... Control 3 LEDs
	 */
    while (1) {
		// Check to see if one second has passed.
		if (TCNT1 >= 31249) {
			// Reset the timer to 0.
			TCNT1 = 0;
			// Calculate the temperature in celcius.
                        // 0 <= tempReading <= 1024 --> 0 <= volts <= 5.0 --> -50 <= degreesCelcius <= 450
			tempReading = ADC;
			volts = (tempReading * 5.0) / 1024;
			degreesCelcius = (volts - 0.5) * 100;
			// Update Serial communications with the degreesCelcius...
			printf("%E \n", degreesCelcius);
			// Turn LEDs ON/OFF to visually represent degreesCelcius.
			if (degreesCelcius < 15) {
				PORTD = 0x00;
			} else if (degreesCelcius < 25) {
				PORTD = (_BV(PORTD3) | _BV(PORTD2));
			} else {
				PORTD = (_BV(PORTD4) | _BV(PORTD3) | _BV(PORTD2));
			}
		}
    }
}

The output on tera term is some whitespace and a question mark ('?').

Thomas Brannan | thomascbrannan@gmail.com

Last Edited: Thu. Jul 20, 2017 - 01:27 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK! Thank you all for your help! I got the code from my last post working by setting those flags in atmel studio's linker options... But wait, there's still one problem. These temperatures are too warm compared to the real temperature in my room! It's actually 73 farenheit in here, but I'm getting a readout of 2.910156E+01C = 29C = 84F. Any idea why my readout is above the real temperature?

Thomas Brannan | thomascbrannan@gmail.com

Last Edited: Thu. Jul 20, 2017 - 01:30 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

TankEngine wrote:
Any idea why my readout is above the real temperature?

In your code you have 2 conversion functions.

One of them assumes a perfect 5V Vcc and the other converts the calculated sensor voltage into an assumed temperature.

So you can tweak the constant values in those 2 formulas a bit to output correct temperature values.

This is what is called calibration.

 

As far as I see here you have not said what kind of sensor you are using to measure the temperature.

Without that information we can not decide if it is just a calibration issue or more is going on.

 

Hint: What does the datasheet of the sensor say about tolerances and accuracy?

 

Edit:

A nice addition & programming exercise would be to add code to calibrate the temperature sensor in software.

You can type values in Tera Term and send those to your AVR.

New calibration values should of course be saved in EEPROM and loaded automatically after a reset.

 

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

Last Edited: Thu. Jul 20, 2017 - 01:53 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I just checked it, it's a TMP36GZ. I will find its data sheet and look into the calibration issue.

Thomas Brannan | thomascbrannan@gmail.com

Last Edited: Thu. Jul 20, 2017 - 02:06 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

TankEngine wrote:
It's actually 73 farenheit in here, but I'm getting a readout of 2.910156E+01C = 29C = 84F. Any idea why my readout is above the real temperature?

Are you sure about the real temperature?
Sensor placing has effect to the reading.
.
MG

I don't know why I'm still doing this hobby

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
		// Check to see if one second has passed.
		if (TCNT1 >= 31249) {
			// Reset the timer to 0.
			TCNT1 = 0;

Can't help thinking that this is crying out to use CTC mode!

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

What is the voltage coming out of the temperature sensor? Then relate that to the value from the adc. Then relate that to your equation and what it reports. The problem is in there somewhere.

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

show us your schematic of the temp sensor and how it connects to the AVR.

 

Jim

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274

 

 

 

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

ki0bk wrote:

show us your schematic of the temp sensor and how it connects to the AVR.

 

Jim

 

 

I'll get to work on producing a schematic of the circuit, but since I've never done that before it may take a day or two to pick a tool and learn how to use it. Any recommendations? In the meantime I'll describe it here: the TMP36GZ is plugged into my breadboard, its three wires are connected to 5V from the arduino uno r3 board, analog input A0 on the arduino and the arduino's ground.

 

Kartman wrote:
What is the voltage coming out of the temperature sensor? Then relate that to the value from the adc. Then relate that to your equation and what it reports. The problem is in there somewhere.

 

Would a multi-meter be the tool for determining the voltage coming out of the temperature sensor? I could order one.

 

clawson wrote:

		// Check to see if one second has passed.
		if (TCNT1 >= 31249) {
			// Reset the timer to 0.
			TCNT1 = 0;

Can't help thinking that this is crying out to use CTC mode!

 

I'm on it! I'll learn about CTC mode tonight and implement it in my code.

 

MicroGyro wrote:
TankEngine wrote:
It's actually 73 farenheit in here, but I'm getting a readout of 2.910156E+01C = 29C = 84F. Any idea why my readout is above the real temperature?
Are you sure about the real temperature? Sensor placing has effect to the reading. . MG

 

I'll check against another thermometer next time I'm at my buddy's house.

Thomas Brannan | thomascbrannan@gmail.com

Last Edited: Fri. Jul 21, 2017 - 01:34 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you are going to continue with this hobby, a multimeter would be a wise acquisition even if it a cheapy one. The problem with electricity is you can't see it, so having tools to measure it will make things much easier for you.

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

Yeah, I've actually been meaning to pick one up for a while. It's just that I don't know what to look for. I suppose I'll do some research on that tonight.

Thomas Brannan | thomascbrannan@gmail.com

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

I updated my project to work with CTC mode, here's the new code:

 

#include <avr/io.h>
#include <stdio.h>
#include <avr/eeprom.h>

#define F_CPU 8000000UL
#define FOSC 16000000UL
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE FOSC/16/USART_BAUDRATE - 1	

// uart_putchar sends a single byte over USART.
int uart_putchar(char c, FILE* stream) {
    if (c == '\n') {
        uart_putchar('\r', stream);
    }
    loop_until_bit_is_set(UCSR0A, UDRE0);
    UDR0 = c;
	return 0;
}

// uart_getchar writes a single byte over USART
// TODO: actually use this function (for calibration)
int uart_getchar(FILE* stream) {
    loop_until_bit_is_set(UCSR0A, RXC0); /* Wait until data exists. */
    return UDR0;
}

// Main()
int main(void) {	

	// Set up analog input
	ADMUX |= _BV(REFS0);
	ADCSRA |= (_BV(ADATE) | _BV(ADSC) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0) | _BV(ADEN));

	// Set up timer
	TCCR1A |= _BV(WGM12);
	OCR1A = 31249;
	TCCR1B |= (_BV(CS12));

	// Set up Serial communication
	UBRR0H = ((BAUD_PRESCALE) >> 8);
	UBRR0L = BAUD_PRESCALE;
	UCSR0B |= (_BV(TXEN0) | _BV(RXEN0));
	UCSR0C |= (_BV(UCSZ01) | _BV(UCSZ00));

	// Redirect STDOUT to USART
	fdevopen(&uart_putchar, &uart_getchar);

	// Configure GPI/O pins 2, 3, and 4 as OUTPUT.
	DDRD |= (_BV(DDD4) | _BV(DDD3) | _BV(DDD2));

	// Declare some variables
	uint16_t tempReading;
	float volts;
	float degreesCelcius;

	// Main While Loop
	/* Once per second...
	 *		... Calculate the temperature.
	 *		... Update Serial communication
	 *		... Control 3 LEDs
	 */
    while (1) {
		// Check to see if one second has passed.
		if (TIFR1 & _BV(OCF1A)) {
			// Clear the OCF1A flag in TIFR by setting it.
                        // This is an unusual bx common to interrupt flags in the AVR.
			TIFR1 = _BV(OCF1A);
			// Calculate the temperature in celcius. -50 <= degreesCelcius <= 450
			tempReading = ADC;
			volts = (tempReading * 5.0) / 1024;
			degreesCelcius = (volts - 0.5) * 100;
			// Update Serial communications with the degreesCelcius...
			printf("%E \n", degreesCelcius);
			// Turn LEDs ON/OFF to visually represent degreesCelcius.
			if (degreesCelcius < 15) {
				PORTD = 0x00;
			} else if (degreesCelcius < 25) {
				PORTD = (_BV(PORTD3) | _BV(PORTD2));
			} else {
				PORTD = (_BV(PORTD4) | _BV(PORTD3) | _BV(PORTD2));
			}
		}
    }
}

Paulvdh wrote:

A nice addition & programming exercise would be to add code to calibrate the temperature sensor in software.

You can type values in Tera Term and send those to your AVR.

New calibration values should of course be saved in EEPROM and loaded automatically after a reset.

 

Haven't forgotten about your comment, Paul! Thanks for this idea. It's what I'm going to be working on this afternoon/evening.

 

I was looking at this Fluke multimeter @ http://www.tmart.com/Fluke-15B-F...

 

It almost seems too good to be true, considering the same multimeter is over $100 on Amazon. $100 is basically my budget for the meter, maybe I could go to $110. Is this Fluke a good purchase? I've done a bit of research and now I know Fluke is a good brand, I know of a few others as well such as Gossen Metrawatt. It would be really cool to get a data-logging meter, but perhaps a good quality data logging meter is out of my budget...?

 

I'm working on creating a schematic using https://circuits.io/lab I hope that's considered a reasonable way to do it. I suppose I could use a free CAD tool like kicad, but to be honest I've got a lot on my plate this summer and don't know if I have time to dive into a serious CAD program (yet).

Thomas Brannan | thomascbrannan@gmail.com

Last Edited: Fri. Jul 21, 2017 - 07:28 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

10 second search for the datasheet:

http://www.analog.com/media/en/t...

Datasheet claims 1deg. Celcius typycal 2Deg. Celcius minumum accuracy.

Checked the datasheet and your basic formula for temperature conversion is correct.

Except that theoretical you should devide by 1023 (max ADC value) and not by 1024, but that is only a 0.1% error.

 

What does this do?

TankEngine wrote:
ADCSRA |= ((1 << ADATE) | (1 << ADSC) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0) | (1 << ADEN));
  Is it using the Vcc of your AVR as a reference for the ADC voltage?

I assume it is because you use 5.0 as a scale value to turn the ADC value to a voltage.

Arduino's do not have a precision regulator in their power supply. Actual voltage depends on the regulator used. Could be between 4.5V and 5.5V

 

Fluke has a good reputation indeed.

But some of the Fluke's (cheaper ones? Old ones?) have pretty slow auto ranging, which would be a show stopper for me.

They also have expensive and hard to obtain fuses. Good for CAT III measurements, but bad news for benchtop measurement for a starting hobbyist.

A Gossen meter would be above your budget.

Dave Jones (EEVblog) has done some nice DMM reviews. (Time consuming to watch though)

I like the Brymen meter he sells and also his latest review of the AN8008, which is an Ali Express Special of USD25.

Note that if you go through with electronics you will probably want 2 or more multimeters.

For example you might want to measure voltage and current at the same time, monitor a certain value continuously while poking around with the 2nd meter.

It's also handy if you distrust you meter, you can double check with the second meter.

 

I am very biased about circuits.io. There are 3 show stoppers for me why I would not even consider touching it.

1). I very much dislike the idea of emulating a Breadboard on a monitor.

    I want to see a real schematic, not real components.

    Breadboards are always messy and a stupid thing to want to emulate.

    Schematics are (should be) drawn in a way that represents the function / working of the circuit.

2). At the end of the road you are handcuffed to autodesk and have to order your PCB's from them.

3). Something with tinkercad? Are they moving into the clouds? I want to keep my feet on firm ground. Don't like fog.

 

Their demo with flashing life-like leds looks impressive at first sight.

But I prefer a spice program which can generate accurate graphs with good readable indexes over fat animated scope emulations with no indexes near the grit.

The whole thing has the nasty smell of trying to lure innocent kids into starting with it and robbing them later.

 

KiCad is one of the jewels of the Open Source world and it is improving fast.

But it comes from a dark past and still has some rough edges, but despite that I like it a lot.

Also Version 5 is expected somewhere this summer and it very likely will have built in Spice simulation.

There are some pretty good "getting started" guides on the KiCad site and the basics of just drawing schematics can be learned in a few hours.

Just as the process from turning your schematic into a PCB with Gerbers. For a simple thing (as in the tutorial) that can be done in another evening.

Designing real complicated PCB's is of course on another level, but KiCad is up to it.

They have some expressive examples on their site. Check out:

http://kicad-pcb.org/made-with-k...

 

Hmm, curious if it works ....

 git clone https://github.com/OLIMEX/OLINUX...

Half an hour later:

Browsed a bit though the schematics & pcb of a 64-bit ARM board.

Yup I like KiCad.

 

And lately I've been promoting almost fee USD5 logic analysers a bit.

They are one of the most useful tools when writing software.

No starting hobbyist should do without them, but lots of people starting with electronics are unfamiliar with them.
A LA transforms a lot of gueswork into knowing.

For instance, Instead of scheaming "Garbage data received" you would have thought:

Gosh I see 4 bytes being transfered and some of them contain 0x00. Why would that be?

https://www.aliexpress.com/whole...
http://sigrok.org/wiki/Supported...

A Quite charming 26 minutes long introduction from & to beginners:
https://www.youtube.com/watch?v=...

Thorough overview (72 minutes) of some more advanced features:
https://www.youtube.com/watch?v=...

 

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

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

Despite my long post, still an addition about data logging meters:

TankEngine wrote:
It would be really cool to get a data-logging meter, but perhaps a good quality data logging meter is out of my budget...?
  With this project you have almost built a data logging temperature meter. You can log anything you can meaure with the 10-bit ADC of your AVR.

 

There are loads of different ADC's available with serial outputs.

If you add a 5V DC-DC converter and a few optocouplers it is also isolated.

For Ideas, check out "data loggeer" on Github:

https://github.com/search?utf8=%...

https://github.com/search?utf8=%...

 

Warning, Brainfart: "Mooshimeter"

https://duckduckgo.com/html?q=mo...

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

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

Paulvdh wrote:

10 second search for the datasheet:
http://www.analog.com/media/en/t...
Datasheet claims 1deg. Celcius typycal 2Deg. Celcius minumum accuracy.
Checked the datasheet and your basic formula for temperature conversion is correct.
Except that theoretical you should devide by 1023 (max ADC value) and not by 1024, but that is only a 0.1% error.

Got it, I corrected my code to use 1023 instead of 1024.

Paulvdh wrote:

What does this do?
TankEngine wrote:
ADCSRA |= ((1 << ADATE) | (1 << ADSC) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0) | (1 << ADEN));
 Is it using the Vcc of your AVR as a reference for the ADC voltage?
I assume it is because you use 5.0 as a scale value to turn the ADC value to a voltage.
Arduino's do not have a precision regulator in their power supply. Actual voltage depends on the regulator used. Could be between 4.5V and 5.5V

Here’s some notes I took on that particular piece of code. I’ve been removing a lot of comments from my code when I post it here…

/* The ADCSRA register is ADC Control and Status Register A...
*    ... Setting the ADATE bit will put the ADC in auto triggering mode, so that we do not have to set a bit for every conversion.
*    ... Setting the ADSC bit will start ADC conversions.
*    ... Setting the DPS2, ADPS1 and ADPS0 bits of the ADCSRA register will set the prescaler to 128; ADCfrequency = F_CPU/prescaler = 8E6Hz/128 = 125kHz
*    ... Setting the ADEN bit in the ADSCRA register activates the ADC.
*/
ADCSRA |= (_BV(ADATE) | _BV(ADSC) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0) | _BV(ADEN));

But, were you actually referring to this line in my code?

volts = (tempReading * 5.0) / 1023;		

This is assuming a perfect 5.0V from Vcc. Fluctuations in the actual value of Vcc would indeed explain why my temperature readings have been inaccurate.

 

I found this stack exchange about a very similar thermometer project with a similar problem @ https://arduino.stackexchange.co... It seems he was having rapidly fluctuating sensor readings due to inconsistent power supply. Suggested solutions included using a capacitor between his temperature sensor and ground, taking an average of several readings for each update, and connecting the sensor to 1.1V internal voltage supply with a voltage divider (at least, that's what I got from the answers).

 

Digging a little deeper, I found a solution that seems better than using a voltage divider. 'Secret Arduino Voltmeter' @ https://provideyourown.com/2012/... talks about using a formula with the internal voltage to calculate Vcc. 

 

Paulvdh wrote:

Fluke has a good reputation indeed.
But some of the Fluke's (cheaper ones? Old ones?) have pretty slow auto ranging, which would be a show stopper for me.
They also have expensive and hard to obtain fuses. Good for CAT III measurements, but bad news for benchtop measurement for a starting hobbyist.
A Gossen meter would be above your budget.
Dave Jones (EEVblog) has done some nice DMM reviews. (Time consuming to watch though)
I like the Brymen meter he sells and also his latest review of the AN8008, which is an Ali Express Special of USD25.
Note that if you go through with electronics you will probably want 2 or more multimeters.
For example you might want to measure voltage and current at the same time, monitor a certain value continuously while poking around with the 2nd meter.
It's also handy if you distrust you meter, you can double check with the second meter.

 

I'm making way through one of Dave Jone's EEVblogs now, that would be EEVblog #91 - $50 Multimeter Shootout @ https://www.youtube.com/watch?v=...

It seems like it would be best to get two $50 meters instead of one $100 meter.

 

Paulvdh wrote:

I am very biased about circuits.io. There are 3 show stoppers for me why I would not even consider touching it.
1). I very much 
dislike the idea of emulating a Breadboard on a monitor.
    I want to see a real schematic, not real components.
    Breadboards are always messy and a stupid thing to want to emulate.
    Schematics are (should be) drawn in a way that represents the function / working of the circuit.
2). At the end of the road you are handcuffed to autodesk and have to order your PCB's from them.
3). Something with tinkercad? Are they moving into the clouds? I want to keep my feet on firm ground. Don't like fog.

Their demo with flashing life-like leds looks impressive at first sight.
But I prefer a spice program which can generate accurate graphs with good readable indexes over fat animated scope emulations with no indexes near the grit.
The whole thing has the nasty smell of trying to lure innocent kids into starting with it and robbing them later.

KiCad is one of the jewels of the Open Source world and it is improving fast.
But it comes from a dark past and still has some rough edges, but despite that I like it a lot.
Also Version 5 is expected somewhere this summer and it very likely will have built in Spice simulation.
There are some pretty good "getting started" guides on the KiCad site and the basics of just drawing schematics can be learned in a few hours.
Just as the process from turning your schematic into a PCB with Gerbers. For a simple thing (as in the tutorial) that can be done in another evening.
Designing real complicated PCB's is of course on another level, but KiCad is up to it.
They have some expressive examples on their site. Check out:
http://kicad-pcb.org/made-with-k...

Hmm, curious if it works ....
 git clone https://github.com/OLIMEX/OLINUX...
Half an hour later:
Browsed a bit though the schematics & pcb of a 64-bit ARM board.
Yup I like KiCad.

 

Ok, I'll work with KiCad on producing that schematic. Sounds like it's not as daunting as I assumed it would be. The thing is, I've had a fair number of software classes, including a MIPS assembly language class, but I've never had an EE class and I'm only starting an electricity & magnetism physics course this coming August. So, you can imagine I don't know a whole lot about electrical diagrams. The book that came with my arduino starter kit has electrical diagrams for each of the projects, but it also has circuits.io like breadboard images and those have really been like a crutch for me.

 

Paulvdh wrote:

And lately I've been promoting almost fee USD5 logic analysers a bit.
They are one of the most useful tools when writing software.
No starting hobbyist should do without them, but lots of people starting with electronics are unfamiliar with them.
A LA transforms a lot of gueswork into knowing.
For instance, Instead of scheaming "Garbage data received" you would have thought:
Gosh I see 4 bytes being transfered and some of them contain 0x00. Why would that be?

https://www.aliexpress.com/whole...
http://sigrok.org/wiki/Supported...
A Quite charming 26 minutes long introduction from & to beginners:
https://www.youtube.com/watch?v=...
Thorough overview (72 minutes) of some more advanced features:
https://www.youtube.com/watch?v=...

 

I will definitely pick one of those up after I've watched the videos!

 

Hey, thanks for the long post. Really helpful.

 

Right now I'm working on calibrating the volts using the information from that 'secret voltmeter' article and I've also been working on getting input from the terminal. Gotta admit I am a bit stumped as to how I get terminal input. In the AVR libc reference manual I found the docs for fdevopen (I'm using c++), but I haven't find an example of how to put it to work... I'm also not sure how to actually send data from Tera Term, as in where do I go in the Tera Term interface? I'll keep looking, but any hints on this issue would be appreciated!

 

 

Thomas Brannan | thomascbrannan@gmail.com

Last Edited: Sun. Jul 23, 2017 - 12:10 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

TankEngine wrote:
Right now I'm working on calibrating the volts using the information from that 'secret voltmeter' article and I've also been working on getting input from the terminal.

You can use that too improve accuracy, but you cannot use it  to get better than +/- 2 degree Celcius from the sensor (datasheet).

So you PROBABLY want to calibrate afterwards, And when calibating you can also calibrate for your particular voltage.

 

A terminal emulator program normally sends all data typed on the keyboard to the serial port, and does that without it showing the data on the screen, so you won't notice.

It only displays the incoming data in the text window.

If you short circuit TxD to RxD then all datat typed on the keyboard is looped back into the program and shown on the monitor.

This should always be your first test for such a program.

 

Then connect RxD & TxD both to the AVR and write a program to echo back every character the AVR receives.

Then you know you have working 2 way communication and you can expand from there.

 

TankEngine wrote:
The book that came with my arduino starter kit has electrical diagrams for each of the projects, but it also has circuits.io like breadboard images and those have really been like a crutch for me.

Sometimes I forget I've been reading schematics for over 30 years now...

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

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

Sometimes I forget I've been reading schematics for over 30 years now...

You young kids! So nothing with 6BL8, EL34, 12AX7, ECL86 etc.....

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

js wrote:
You young kids! So nothing with 6BL8, EL34, 12AX7, ECL86 etc.....
  Nope. I positively refuse to have anything to do with those archaic light bulbs :)

On hackaday I once saw a cpu built with discrete transistors, which was a beautiful build. It should be somewhere in here:

http://hackaday.com/?s=cpu+trans...

 

But I stopped @ page 8, which refers to an electromechanical version with relays:

http://hackaday.com/2010/11/18/e...

 

CRT's have become obsolete and even normal lightning has turned mostly into solid state LED's nowadays.

Trying to keep up with modern developments is hard enough as it is for my poor brain.

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

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

So I updated my code to calculate the Vcc using the readVcc() function from the 'Secret Arduino Voltmeter' article, and now I'm getting some odd results. It is reading a near-zero Vcc, so the calculated temperature is very wrong. I suspect that the problems with readVcc() have something to do with the way I've modified it, notably I tried to make it work with auto-triggering mode and I made it return volts instead of millivolts, and I made it reset the changes to ADMUX.

 

I'm going to start posting links to my code on github instead of putting them in my post. I think that will be nicer for everyone because it will have syntax highlighting and I won't be removing my comments to save space. Here it is: https://gist.github.com/ThomasCB...

 

I'm going to look into the logic analyzers and I'll order a multimeter or two tonight. When I get the Vcc measurement correct I will work on calibration from terminal input. Once I get temperature readings that are more or less accurate, I'll refactor the code into macros or functions (should have been doing this from the beginning). I'll count it as done at that point and move onto part 2: comparing the external temperature sensor to the internal temperature sensor. My buddy suspects that the internal temperature sensor will be hotter, I say no because the AVR is such a low power chip.

 

EDIT: I updated the link to a version with better usart output. Here's a sample:

 

Vcc = 7.006490E-45      tempReading = 3.138909E-43      volts = 2.277951E-41    degreesCelcius = -8.607310E+09
Vcc = 5.605190E-45      tempReading = 3.166935E-43      volts = 0.000000E+00    degreesCelcius = -8.640864E+09
Vcc = 7.006490E-45      tempReading = 3.138909E-43      volts = 2.277951E-41    degreesCelcius = -8.607310E+09
Vcc = 5.605190E-45      tempReading = 3.166935E-43      volts = 0.000000E+00    degreesCelcius = -8.640864E+09
Vcc = 7.006490E-45      tempReading = 3.138909E-43      volts = 2.277951E-41    degreesCelcius = -8.607310E+09
Vcc = 5.605190E-45      tempReading = 3.166935E-43      volts = 0.000000E+00    degreesCelcius = -8.640864E+09
Vcc = 7.006490E-45      tempReading = 3.138909E-43      volts = 2.277951E-41    degreesCelcius = -8.607310E+09
Vcc = 5.605190E-45      tempReading = 3.166935E-43      volts = 0.000000E+00    degreesCelcius = -8.640864E+09
Vcc = 7.006490E-45      tempReading = 3.138909E-43      volts = 2.277951E-41    degreesCelcius = -8.607310E+09
Vcc = 5.605190E-45      tempReading = 3.166935E-43      volts = 0.000000E+00    degreesCelcius = -8.640864E+09
Vcc = 7.006490E-45      tempReading = 3.138909E-43      volts = 2.277951E-41    degreesCelcius = -8.607310E+09
Vcc = 5.605190E-45      tempReading = 3.166935E-43      volts = 0.000000E+00    degreesCelcius = -8.640864E+09

Thomas Brannan | thomascbrannan@gmail.com

Last Edited: Mon. Jul 24, 2017 - 03:45 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are really making it difficult for yourself! Using auto trigger mode and randomly reading the adc result is not a good idea. When you change the mux, you need to wait for two results as you might change the mux midway through a conversion. So the result might be the input before you changed the mux or the one after. Roll the dice and see what you got.
So, avoid auto mode and make your life easier. When debugging, dump the raw value before you do any math - that way you can validate the reading manually.
Without a multimeter, you can use fixed resistors to create specific voltages on your input.

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

Hmm, so what I should do is ditch auto-trigger mode throughout my code? Manually set ADSC for each conversion? I'll get right on it.

 

EDIT: I'm reading through section 24.3 of the datasheet "starting a conversion" as well as the ADC tutorial @ https://www.avrfreaks.net/forum/t...

 

EDIT 2: I modified my code not to use auto-trigger mode. I'm working with a readADC() function loosely based on a function @ http://maxembedded.com/2011/06/t...

 

Here's the gist: https://gist.github.com/ThomasCB...

 

Here's sample output. It's about the same as last time, readVcc() and readADC() are both producing near-zero results. I suppose there must be an error somewhere in my configuration of the ADC?

 

Vcc = 7.006490E-45      tempReading = 1.975831E-43      volts = 0.000000E+00    degreesCelcius = -8.640864E+09
Vcc = 7.006490E-45      tempReading = 1.975831E-43      volts = 0.000000E+00    degreesCelcius = -8.640864E+09
Vcc = 7.006490E-45      tempReading = 1.975831E-43      volts = 0.000000E+00    degreesCelcius = -8.640864E+09
Vcc = 7.006490E-45      tempReading = 1.975831E-43      volts = 0.000000E+00    degreesCelcius = -8.640864E+09
Vcc = 7.006490E-45      tempReading = 1.975831E-43      volts = 0.000000E+00    degreesCelcius = -8.640864E+09
Vcc = 7.006490E-45      tempReading = 1.975831E-43      volts = 0.000000E+00    degreesCelcius = -8.640864E+09
Vcc = 7.006490E-45      tempReading = 1.975831E-43      volts = 0.000000E+00    degreesCelcius = -8.640864E+09
Vcc = 7.006490E-45      tempReading = 1.975831E-43      volts = 0.000000E+00    degreesCelcius = -8.640864E+09
Vcc = 7.006490E-45      tempReading = 1.961818E-43      volts = 0.000000E+00    degreesCelcius = -8.640864E+09

Thomas Brannan | thomascbrannan@gmail.com

Last Edited: Mon. Jul 24, 2017 - 06:11 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

TankEngine wrote:

Hmm, so what I should do is ditch auto-trigger mode throughout my code? Manually set ADSC for each conversion? I'll get right on it.

 

EDIT: I'm reading through section 24.3 of the datasheet "starting a conversion" as well as the ADC tutorial @ https://www.avrfreaks.net/forum/t...

 

EDIT 2: I modified my code not to use auto-trigger mode. I'm working with a readADC() function loosely based on a function @ http://maxembedded.com/2011/06/t...

 

Here's the gist: https://gist.github.com/ThomasCB...

 

Here's sample output. It's about the same as last time, readVcc() and readADC() are both producing near-zero results. I suppose there must be an error somewhere in my configuration of the ADC?

 

Vcc = 7.006490E-45      tempReading = 1.975831E-43      volts = 0.000000E+00    degreesCelcius = -8.640864E+09
Vcc = 7.006490E-45      tempReading = 1.975831E-43      volts = 0.000000E+00    degreesCelcius = -8.640864E+09
Vcc = 7.006490E-45      tempReading = 1.975831E-43      volts = 0.000000E+00    degreesCelcius = -8.640864E+09
Vcc = 7.006490E-45      tempReading = 1.975831E-43      volts = 0.000000E+00    degreesCelcius = -8.640864E+09
Vcc = 7.006490E-45      tempReading = 1.975831E-43      volts = 0.000000E+00    degreesCelcius = -8.640864E+09
Vcc = 7.006490E-45      tempReading = 1.975831E-43      volts = 0.000000E+00    degreesCelcius = -8.640864E+09
Vcc = 7.006490E-45      tempReading = 1.975831E-43      volts = 0.000000E+00    degreesCelcius = -8.640864E+09
Vcc = 7.006490E-45      tempReading = 1.975831E-43      volts = 0.000000E+00    degreesCelcius = -8.640864E+09
Vcc = 7.006490E-45      tempReading = 1.961818E-43      volts = 0.000000E+00    degreesCelcius = -8.640864E+09

But a big problem with our code is these lines:

// Measure Vcc
vcc = readVcc();
// Calculate the temperature in celcius 0 <= tempReading <= 1023 --> 0 <= volts <= 5.0 --> -50 <= degreesCelcius <= 450
tempReading = ADC;

The readVcc function sets ADMUX channel 0, starts a conversion, waits until done and reads the ADC register. It does also restore the original ADMUX channel. However when you read the ADC register value after that call, the contents will be the same as before (since you have not started any new conversion).

 

EDIT: looked at the ATmega328 datasheet and I am confused. What channel is actually selected with the conditional code? 

 

You need to start a conversion and wait until done before reading the ADC. Essentially the same code as in the readVcc function (so a hint that maybe you could refactor that function and pass ADMUX channel as parameter...).

 

But I would also suggest you avoid float and calculations, and start by just printing the raw ADC value (in decimal format).

/Jakob Selbing

Last Edited: Mon. Jul 24, 2017 - 08:19 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Vcc = 7.006490E-45

That's a very meaningless value:

 

0.00000000000000000000000000000000000000000000700649 V

 

I bet your Vcc is not that value!

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

'0' is not the same as 0. That's one defect. The code is riddled with different types so the calculations won't be anywhere near sensible.
Eg: 1125.3L. Long is an integer type, so that gets truncated to 1125. 1125/1023 as an integer is 1.
So your vcc value will be 0 or 1.
Pass that into an equally defective calculation and you get rubbish. So be aware of your integers and float variables.

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

Do some work with the raw ADC values.

I'm sure your ADC just has a single bit of noise.

 

Clawson is right, but still I disagree (a little bit)

Vcc = 7.006490E-45 is not a completely meaningless value.

If you look at the first table you see 2 values, (both less than 0.00000).

Which very means you have only 2 different ADC values.

 

Note:

You are also using the wrong formula.

AVR's don't work if Vcc is < 2V and 1E-45 is Much smaller than 1 as Clawson pointed out.

If you are not familiar with floting point numbers.

The number after the "E" is the exponent. Negative exponents always indicate small numbers.

https://en.wikipedia.org/wiki/Si...

 

When debugging you formulas it is usefull to print both the raw input (ADC value) and the end result to a terminal.

 

 

I'm not browsing to github for small code snippets. Post them inline if you want them commented.

 

 

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

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

A little update, I've got readVcc() working! Big thanks to Kartman for pointing out that long is an integer type, and to everyone else who chimed in.

 

Now, I could use a little help with my readADC() function. It's still giving junk values. Maybe the problem is I should be using a 01.uF capacitor in my circuit? I've been trying to get readADC() to work for a while now and I've tried everything I can think of... Here is the code:

// readADC() loosely based on function @ http://maxembedded.com/2011/06/the-adc-of-the-avr/
uint16_t readADC(uint8_t c) {
	c &= 0b00001111;			// Clear all bits of c except 4 least significant bits
	uint8_t tempADMUX = ADMUX;		// Save the value of ADMUX
	ADMUX = 0x0;				// Clear ADMUX
	ADMUX |= (_BV(REFS0) | c);		// Measure channel designated by c against Vcc reference
	_delay_ms(2);				// Wait for Vref to settle
	ADCSRA |= _BV(ADSC);			// Start conversion
	while (bit_is_set(ADCSRA,ADSC)) {};     // Wait while measuring.
	uint16_t result = ADC;			// Capture the result of the conversion.
	ADMUX = tempADMUX;			// Restore ADMUX.
        return result;				// Return the result of the conversion.
}

Re; the advice to log my raw ADC reading to the terminal. That's what 'tempReading' is, it's the raw ADC reading from the TMP36GZ. Unless you guys mean I should do something different?

 

I will be responding to some of the other feedback soon, just wanted to put this out there.

 

EDIT: I'm working with casting the types... getting some improvements, maybe? Will report back.

 

EDIT 2: I changed all my float variables to doubles. I still have the problem with readADC() providing a weird result, but it seems closer to real values? Perhaps. Here's some sample output:

 

Vcc = 5.023661E+00      tempReading = 1.490000E+02      volts = 7.316965E-01    degreesCelcius = 2.316965E+01
Vcc = 5.001334E+00      tempReading = 1.720000E+02      volts = 8.408889E-01    degreesCelcius = 3.408889E+01
Vcc = 4.979204E+00      tempReading = 1.840000E+02      volts = 8.955752E-01    degreesCelcius = 3.955752E+01
Vcc = 4.979204E+00      tempReading = 1.840000E+02      volts = 8.955752E-01    degreesCelcius = 3.955752E+01
Vcc = 4.979204E+00      tempReading = 1.840000E+02      volts = 8.955752E-01    degreesCelcius = 3.955752E+01
Vcc = 4.979204E+00      tempReading = 1.840000E+02      volts = 8.955752E-01    degreesCelcius = 3.955752E+01
Vcc = 4.979204E+00      tempReading = 1.840000E+02      volts = 8.955752E-01    degreesCelcius = 3.955752E+01
Vcc = 4.979204E+00      tempReading = 1.840000E+02      volts = 8.955752E-01    degreesCelcius = 3.955752E+01

 

Thomas Brannan | thomascbrannan@gmail.com

Last Edited: Mon. Jul 24, 2017 - 10:11 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The raw adc value is an integer between 0 and 1023. Not quite what we're seeing.
Avr-gcc doesn't do double - you can observe this in the number of digits printed. Also note to force float calculations your constants should have a decimal in them. Eg 255 is integer, 255.0 will be treated as a float. Whilst you can mix integer and float types in an equation, C has rules as to how they will be interpreted. Ignore these rules and the compiler might perform an integer calc when you want a float. Casting can force the compiler's hand but if the result variable is an integer to a float calc then the result will be truncated.

Last Edited: Mon. Jul 24, 2017 - 10:41 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ah, I see. I changed the printf() statement to print the tempReading as an int (NB it is of type uint16_t, but I was casting it to a float/double in the printf() statement). Here is new sample output:

 

Vcc = 5.023661E+00      tempReading = 149       volts = 7.316965E-01    degreesCelcius = 2.316965E+01
Vcc = 5.001334E+00      tempReading = 172       volts = 8.408889E-01    degreesCelcius = 3.408889E+01
Vcc = 4.979204E+00      tempReading = 184       volts = 8.955752E-01    degreesCelcius = 3.955752E+01
Vcc = 4.979204E+00      tempReading = 184       volts = 8.955752E-01    degreesCelcius = 3.955752E+01
Vcc = 4.979204E+00      tempReading = 184       volts = 8.955752E-01    degreesCelcius = 3.955752E+01
Vcc = 4.979204E+00      tempReading = 184       volts = 8.955752E-01    degreesCelcius = 3.955752E+01
Vcc = 4.979204E+00      tempReading = 184       volts = 8.955752E-01    degreesCelcius = 3.955752E+01
Vcc = 4.979204E+00      tempReading = 184       volts = 8.955752E-01    degreesCelcius = 3.955752E+01
Vcc = 4.979204E+00      tempReading = 184       volts = 8.955752E-01    degreesCelcius = 3.955752E+01
Vcc = 4.979204E+00      tempReading = 184       volts = 8.955752E-01    degreesCelcius = 3.955752E+01
Vcc = 4.979204E+00      tempReading = 184       volts = 8.955752E-01    degreesCelcius = 3.955752E+01
Vcc = 4.979204E+00      tempReading = 184       volts = 8.955752E-01    degreesCelcius = 3.955752E+01
Vcc = 4.979204E+00      tempReading = 184       volts = 8.955752E-01    degreesCelcius = 3.955752E+01

 

EDIT: I changed the doubles back to floats because, as Kartman mentioned, doubles aren't supported in avr-gcc. It didn't really change the results.

Thomas Brannan | thomascbrannan@gmail.com

Last Edited: Mon. Jul 24, 2017 - 10:46 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

149 equates to around 23C with a 5V reference.

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

Ok, I'll look into my equations then. Clearly something is wrong.

EDIT: Well, *something* is wrong anyways. Must not be the equations since you say that 194 should equate to 23C. The weather in San Francisco today is around 18C, though. So my readings are all hotter than the real temperature.

EDIT 2: Maybe it is time to implement calibration from the terminal to EEPROM.

Thomas Brannan | thomascbrannan@gmail.com

Last Edited: Mon. Jul 24, 2017 - 11:02 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'd suggest you venture down to Fry's where they have velleman multimeters for $4.99 according to my quick Google.

Also, holding the tmp device with your fingers should give around 30C readings.

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

Sadly there is no Fry's in San Francisco. No other electronics store, either. I ordered a multimeter online.

 

For now I'm going to work on calibrating the sensor from the terminal. I'll just enter a multiplier that modifies the reading and save it to EEPROM, like Paulvdh suggested earlier.

 

EDIT: I thought to test it out with the arduino IDE code from the starter kit book. It gives the same too-high temperature, around 40C.

Thomas Brannan | thomascbrannan@gmail.com

Last Edited: Tue. Jul 25, 2017 - 12:06 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No Fry's in San Francisco?  Yikes.  I thought that's where they got started.  Maybe a few in the suburbs not too far away via BART?  Jameco's down the peninsula - way, but I don't think they have a walk-up window.  Mail-order only.  S.

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

Granted, it is probably a 1 hour or so trip each way. The Concord store is a bit closer than Sunnyvale. Where's RadioShack when you need them!!!

Looks like we've ruled out software issues for the moment - leaving only hardware. How is the tmp36 hooked up? How long are the wires?

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

Scroungre wrote:

No Fry's in San Francisco?  Yikes.  I thought that's where they got started.  Maybe a few in the suburbs not too far away via BART?  Jameco's down the peninsula - way, but I don't think they have a walk-up window.  Mail-order only.  S.

Yeah, the lack of an electronics store is kinda surprising. Goes to show what a small city SF really is.

Kartman wrote:

Granted, it is probably a 1 hour or so trip each way. The Concord store is a bit closer than Sunnyvale. Where's RadioShack when you need them!!!

Looks like we've ruled out software issues for the moment - leaving only hardware. How is the tmp36 hooked up? How long are the wires?

Here's a picture of my circuit, sorry I know that's not an outstanding way to share the circuit but it's the best I can do until I have time to figure out KiCad... The tmp36 is installed with the round side facing away from the arduino, per the book's instructions. Connected to 5V at the top, A0 in the middle and GND at the bottom. Also three leds with 220 ohm resistors. The wires I used are the ones that came with the kit, none are particularly long.

 

Thomas Brannan | thomascbrannan@gmail.com

Last Edited: Tue. Jul 25, 2017 - 04:17 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'd suggest a 100nF cap across the 0V and 5V and probably another from 0V to the analog signal.

Surely there's some hippy makerspace in SF where you can network? Make friends and bot components.

If you're going to San Francisco,
Be sure to bring, some multimeters in your bag....

Last Edited: Tue. Jul 25, 2017 - 05:28 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My kit came with 100uF capacitors, think that would do the trick?

 

EDIT: did a search for makerspaces... I may swing by this TechShop place. There are also some interesting meetup groups. 

Thomas Brannan | thomascbrannan@gmail.com

Last Edited: Tue. Jul 25, 2017 - 06:14 AM

Pages