Store › Forums › Video Experimenter › Bugs/Problems › OneWire Temp causing jumpy overlay
- This topic has 16 replies, 2 voices, and was last updated 12 years, 11 months ago by pinkstond.
-
AuthorPosts
-
December 2, 2011 at 5:42 pm #469pinkstondMember
On my project everything was displaying and working correctly! Until… I added a this:
http://bildr.org/2011/07/ds18b20-arduino/
After adding this the text is jumping from it’s original position to various spots horizontal to it’s current position. It’s also jumping up and down by 1-2 px. As soon as I take out the “getTemp” float, then the text is all back to normal. I’ll be the first to admit I am very new to arduino in general, I’m quick to copy,paste, modify and google for hours until I learn things and get them to work how I want. However I’ve been stumped on this one for some time. I’m guessing maybe it’s some kind of compatibility issue, or maybe some kind of interference?
Regardless, I would very much appreciate any help I can get in tracing and correcting this problem.
Thanks!
DerekP.S. To see the undesired effect, visit this link: http://homewebwatch.com/test123.php?passwd=helpme (not the fastest, but it gets the point across)
December 2, 2011 at 6:01 pm #1216MichaelKeymasterThe example on that site has the sensor connected to pin 2 on the Arduino. Is that what you did? Because that would mess up the video timing, since the Video Experimenter uses pin 2. If so, you could try another pin (like 3).
December 2, 2011 at 6:02 pm #1283pinkstondMemberSorry, should have mentioned that. It is currently on D10.
December 2, 2011 at 10:27 pm #1284MichaelKeymasterIs your version of the OneWire library disabling/enabling interrupts? The current version does this, and that will interfere with the video timing. The TVout library relies on interrupts to perform the timing.
How often are you polling the sensor? You could arrange for the sensor reading to only happen during the video blanking interval. TVout has a way to set a hook function to be called during the VBI. You pass a pointer to the function you want called.
tv.set_vbi_hook(&readSensor);
Where you have a function called readSensor that does the work:
void readSensor() {
// do the work of reading the sensor
}And you certainly don’t need to read the sensor 60 times per second. Use a counter to arrange for it to happen every 60th call to readSensor or something. Make sense?
December 2, 2011 at 11:01 pm #1285pinkstondMemberHrm, I’m sure I am doing this all wrong… But when ever I did what you said I don’t get anything displayed at all. Right after it uploads I get a big block of squiggly lines that fill the screen for a second and then nothing..
December 2, 2011 at 11:25 pm #1286pinkstondMemberI’ve also tried this method:
Ignore the sloppiness, and the noobness. Lots of copy and pasting and moving stuff around to see if it’ll work right.
#include
#include
#include
#define W 136
#define H 96
OneWire ds1(10);
TVout tv;
unsigned char x,y;
unsigned char originx = 5;
unsigned char originy = 80;
unsigned char plotx = originx;
unsigned char ploty = 40;
char emf[10];
char temp[4];
float val;
float tmp;
unsigned short avg;
char inVBI;
void setup() {
tv.set_vbi_hook(&setVBIFlag);
tv.begin(NTSC, W, H);
initOverlay();
tv.select_font(font6x8);
tv.fill(0);
Serial.begin(9600);
}
void initOverlay() {
TCCR1A = 0;
TCCR1B = _BV(CS10);
TIMSK1 |= _BV(ICIE1);
EIMSK = _BV(INT0);
EICRA = _BV(ISC11);
}
ISR(INT0_vect) {
display.scanLine = 0;
}
void setVBIFlag() {
inVBI = true;
}
void loop() {
if (inVBI) {
delay(2000);
byte data1[3];
byte addr1[0];
if ( !ds1.search(addr1)) {
//no more sensors on chain, reset search
// ds1.reset_search();
// return -1000;
}
ds1.reset();
ds1.select(addr1);
ds1.write(0x44,1); // start conversion, with parasite power on at the end
byte present = ds1.reset();
ds1.select(addr1);
ds1.write(0xBE); // Read Scratchpad
//No Prob Here
for (int p = 0; p < 9; p++) { // we need 9 bytes
data1[p] = ds1.read();
}
ds1.reset_search();
float MSB = ((data1[1] << 8));
float LSB = (data1[0]);
float tempRead = (MSB + LSB); //using two's compliment
float tmp = tempRead / 16 * 1.8 + 32;
dtostrf(tmp, 1, 1, temp);
int ary1[300];
for(int b = 0; b < 300; ++b) {
ary1 = analogRead(1);
avg += ary1;
}
val = avg / 300;
val = constrain(val, 0, 100);
val = map(val, 0, 100, 0, 255);
val = val *.1;
dtostrf(val, 1, 1, emf);
avg = 0;
inVBI = false;
}
tv.print(0, 89, "EMF");
tv.print(20, 89, emf);
tv.print(24, 80, "*F");
tv.print(0, 80, temp);
}
December 3, 2011 at 2:47 pm #1279MichaelKeymasterpinkstond, if you want people to help you with your code, you need to organize it and format it so it’s readable. People are busy, so you need to make the effort…
You have a delay(2000) within the “if (inVBI)” block. The VBI is only a couple of milliseconds long, so you can’t wait for 2 seconds. Move that delay out of there.
December 3, 2011 at 7:20 pm #1282pinkstondMemberI’m sorry, I’m really new to this and sometimes when I work days on a simple issue like that I get too lazy and quick to get an answer. The code below I stripped out the information that is not relevant to this issue and organized it the best I can.
#include
#include
#include
OneWire ds1(10);
TVout tv;
unsigned char x,y;
unsigned char originx = 5;
unsigned char originy = 80;
unsigned char plotx = originx;
unsigned char ploty = 40;
char temp[10];
void setup() {
tv.begin(NTSC, 120, 96);
initOverlay();
tv.select_font(font6x8);
tv.fill(0);
tv.set_vbi_hook(&getTemp);
}
void initOverlay() {
TCCR1A = 0;
TCCR1B = _BV(CS10);
TIMSK1 |= _BV(ICIE1);
EIMSK = _BV(INT0);
EICRA = _BV(ISC11);
}
ISR(INT0_vect) {
display.scanLine = 0;
}
void loop() {
tv.print(23, 80, "*F");
tv.delay_frame(1);
dspData(); //Display the recieved temp from getTemp
}
//Get the temp from the sensor.
void getTemp() {
byte data1[12];
byte addr1[8];
if ( !ds1.search(addr1)) {
}
ds1.reset();
ds1.select(addr1);
ds1.write(0x44,1);
byte present = ds1.reset();
ds1.select(addr1);
ds1.write(0xBE);
for (int p = 0; p < 9; p++) {
data1[p] = ds1.read();
}
ds1.reset_search();
float MSB = ((data1[1] << 8));
float LSB = (data1[0]);
float tempRead = (MSB + LSB);
float tmp = tempRead / 16 * 1.8 + 32 - 5; //Convert Celsius to Fahrenheit
dtostrf(tmp, 1, 1, temp); //Convert the float to a string so it can be displayed properly
}
//Display the temp
void dspData() {
tv.print(0, 80, temp);
}I didn’t know if I needed to call the getTemp function in the loop, but I have tried both ways. With the code above I end up getting this on the video output:
December 3, 2011 at 7:53 pm #1276MichaelKeymasterIt’s better to set a flag in your VBI hook function, then act on that flag in loop(). The reason is that you don’t want to do sensor communication in the TVout interrupt handler.
So I’d try this:
Declare a flag and a count variable at the beginning of your code.volatile boolean inVBI = false;
int vbiCount = 0;In setup(), do this:
tv.set_vbi_hook(&setVBIFlag);
Implement setVBIFlag as you did before:
void setVBIFlag() {
inVBI = true;
}loop() should inspect the inVBI variable and get sensor data only once per second
void loop() {
if (inVBI) {
if (++vbiCount == 60) {
// only fetch temperature every 60th frame (once per second)
getTemp();
tv.print(23, 80, "*F");
dspData(); //Display the recieved temp from getTemp
vbiCount = 0; // reset counter
}
inVBI = false; // reset flag
}
}Also, keep in mind that comminicating with a sensor like this in an interrupt driven program is not really a beginner project. It’s much easier to simply read an analog sensor versus one that has its own communication protocol. The current version of the OneWire library turns interrupts on and off, and that interferes with video.
December 3, 2011 at 8:36 pm #1277pinkstondMemberAdded and arranged things as you said to, and it’s back to it’s original behavior. The temp shows up fine, but when the temp updates it jumps across the screen. It’s almost like the VBI isn’t enough time for the code to run? Or the VBI isn’t happening?
I drove around town and tried to find a analog temp sensor since I’ve lost so much time on this, but was unable to find one locally.
I think I might just find an analog one online, but it would be nice to find the solution to this issue to possibly help others in the same position in the future. I just don’t want to use up more of your time.
December 3, 2011 at 9:09 pm #1278MichaelKeymasterI think your sensor code is working fine since the temperature value is changing (I’m looking at your live feed).
Maybe your string buffer handling isn’t working right. I use sprintf, like:
sprintf(temp, "%.1f", tmp);
You can verify whether your string handling is working by just printing a constant string to the screen and see if it jumps around.
tv.print(0, 80, "foo");
December 3, 2011 at 9:14 pm #1269MichaelKeymaster…this is cool that I’m watching you experiment on your live feed….
looks like a constant “?” and “foo” still jump…
December 3, 2011 at 9:18 pm #1270pinkstondMemberNope. Its not the string, it’s the part of the sensor reading. I did have another analog sensor hooked up and was displaying it on the screen the same way, and it never skipped until I added the code under the getTemp function. I’ve tried to narrow down what part of that is doing it with no luck.
I added
tv.print(0, 70, "foo");
and commented out these two
tv.print(0, 80, temp);
dtostrf(tmp, 1, 1, temp);and foo is still blinking from what I am guessing is the part where it’s pulling the info from the sensor.
December 3, 2011 at 9:27 pm #1271MichaelKeymasterYeah, the OneWire library is messing with interrupts. Please look at the OneWire code and see if it is turning interrupts on and off. If you see lines “noInterrupts()” and “interrupts()”, comment them out. I think the communication might still work.
I’m sitting here watching you — it’s funny. I can see when you are uploading new code onto the Arduino. My kids think it’s cool, too.
December 3, 2011 at 9:35 pm #1272MichaelKeymaster“Hey Michael’s Kids”….thanks buddy.
-
AuthorPosts
- You must be logged in to reply to this topic.