MicroView and Phoenard Arduino Forum
Sign up Calendar Latest Topics
 
 
 


Reply
  Author   Comment   Page 2 of 2      Prev   1   2
naterad

Junior Member
Registered:
Posts: 15
Reply with quote  #16 
Absolutely...Ill try to shoot a video tonight for my youtube channel.

I will also make another one later when i get a solder-able breadboard to make it all nice and contained in a small package.  I just ordered a 2 relay board last night to replace my four model so it will take up less room.

 

naterad

Junior Member
Registered:
Posts: 15
Reply with quote  #17 
Check it out :-)

MLXXXp

Avatar / Picture

Senior Member
Registered:
Posts: 75
Reply with quote  #18 
Good video! [thumb]
micro

Avatar / Picture

Administrator
Registered:
Posts: 141
Reply with quote  #19 
Just wanted to say what a brilliant thread ... seeing the microview used for a practical purpose.

As always brilliant contribution by MLXXXp, and also thanks to Naterad for loading the video, very interesting.
naterad

Junior Member
Registered:
Posts: 15
Reply with quote  #20 
Hey MLXXXp

Its me again [smile]

Ive been having a very crude setup having the microview and wires dangle from my tank but it has been working perfectly with the relays and everything. I want to make it alot cleaner so have decided to take some time and do such.

One thing i didnt like about my sensor was it had a metal end and is starting to rust so i bought a new/better one covered in plastic. With this new one i was curious to see how far the temp's differed from the metal one so I took the stock code located here
http://bildr.org/2011/07/ds18b20-arduino/
and hooked up to my arudino uno.

I was shocked to find the serial temperature is 1.5-2 degrees off from what the microview was showing.
So just for further investigation i took the same code and put it on the microview and opened the serial console and it was 1.5-2 degrees higher than what the microview screen was displaying.

This tells me the sensors are identical and working. Is there a chance the code you supplied me is for some reason reading lower than the serial console is actually displaying?
Here is the final code you gave me back then that i have been using.
https://mega.nz/#!fEkk0aYB!INPUGQRqDonWHAAtBN9O0fotShuJdCZyRIH3_MiTaoo

Thanks as always!
Nate

 

MLXXXp

Avatar / Picture

Senior Member
Registered:
Posts: 75
Reply with quote  #21 
Nate,

I compared my code to the original and noticed that I was missing a delay to wait for conversion, in the getTemp() function. I don't know if I accidentally deleted it after copying the code or if it's been added to the original recently.

Anyway, I've now added this delay to my sketch, in the same repository:
https://github.com/MLXXXp/MicroViewThermostat

(Remember to change the heater and alert temperature settings to your desired values before uploading it)

I'm not sure it will change anything, though. The sensor outputs the temperature digitally and the code just converts it to Fahrenheit before displaying it.

The original code outputs the temperature in Celsius. How are you converting it to Fahrenheit for comparison with my sketch on the MicroView?

naterad

Junior Member
Registered:
Posts: 15
Reply with quote  #22 
You were right that didnt do anything.  The microview is showing 80.7 on the screen and my other sensor hooked up to my uno via the serial console says 83.4
MLXXXp

Avatar / Picture

Senior Member
Registered:
Posts: 75
Reply with quote  #23 
There's only one other thing I can think of that may be causing the difference. It may be that the sensor draws more power when doing a temperature reading. The original program reads the temperature more often, so the power that it uses during reading generates more heat, thus self-heating the sensor more.

You could try adding a delay(2000); at the end of the loop() function of the original program so it reads the temperature at the same rate as my MicroViewThermostat sketch.


void loop(void) {
  float temperature = getTemp(); //will take about 750ms to run
  Serial.println(temperature);
  delay(2000); // 2 second delay between readings
}
naterad

Junior Member
Registered:
Posts: 15
Reply with quote  #24 
I figured it out by poking around with some of your code.

No delay was needed.

Turns out this is what fixed it.

Original:

#ifdef FAHRENHEIT_SCALE
temperature = temperature * 9/5 + 32;
#endif

Modified: (turned off math)

#ifdef FAHRENHEIT_SCALE
temperature = temperature ;//* 9/5 + 32;
#endif

2nd thing I changed
Original:

float TemperatureSum = tempRead / 16;

Modified
float TemperatureSum = tempRead / 5.216;


So the question I have next is what did the 9/5=32 do?  and what was done by dividing by 16?

Thanks!
Nate
MLXXXp

Avatar / Picture

Senior Member
Registered:
Posts: 75
Reply with quote  #25 
Quote:
Originally Posted by naterad
So the question I have next is what did the 9/5=32 do?  and what was done by dividing by 16?

Look at the comment at the start of the getTemp() function:
// Returns the temperature from one DS18S20 in DEG Celsius

You, living in the U.S.A, which is one of the few remaining countries that doesn't use the metric system, wanted the temperature displayed in Fahrenheit.

The formula for converting the Celsius temperature returned by the sensor to Fahrenheit is:
Fahrenheit = Celsius X 9/5 + 32

http://www.rapidtables.com/convert/temperature/how-celsius-to-fahrenheit.htm

The reason for the divide by 16 is:
The sensor can read temperatures in fractions of a degree but sends the value as an integer. In order to retain the fractional part of the reading, it multiplies the reading by 16 before sending it (shifts it left 4 bits), so the value you get from the sensor is 16 times the actual temperature (in Celsius). After reading the value from the sensor, the program has to divide by 16 to get the true temperature.

Quote:
Originally Posted by naterad
No delay was needed.

A delay is needed. Without it you're probably getting the reading from the previous conversion, not the one that was currently asked for.

You said my program gives readings that are 1.5 to 2 degrees low. Are you sure it's not the original code giving readings that are 1.5 to 2 degrees high? Have you compared the readings to another thermometer that is known to be accurate, such as a standard glass aquarium thermometer?

Assuming the sensor is giving the correct temperature in Celsius, the changes you made will only convert correctly for one specific temperature, that being 77.44433 Fahrenheit (25.24685 Celsius). All other conversions from Celsius to Fahrenheit will be wrong.

What does your code read with the sensor at room temperature? What if you put it in some ice water (which should be at just above 32 degrees Fahrenheit)?

Here's a chart of Celsius from the sensor, converted to Fahrenheit using the standard formula, and converted using your method:

Celsius Fahrenheit Your Method
   0        32           0
   5        41       15.33742
  10        50       30.67485
  15        59       46.01227
  20        68       61.34969
  25        77       76.68712
25.24685 77.44433    77.44433
  30        86       92.02454
  35        95      107.36196
  40       104      122.69939
naterad

Junior Member
Registered:
Posts: 15
Reply with quote  #26 
Quote:
Have you compared the readings to another thermometer that is known to be accurate, such as a standard glass aquarium thermometer?


Yes just to be sure both sensors were correct I used my lab grade chemistry thermometer and it reads 81.6-82F which is exactly what both sensors are showing via serial monitor if i run just the ds18b20 code.  Both sensors running at the same time (one on uno and other on microview)--So both sensors are reading identical and accurate.

I am wondering if perhaps we might be looking at different code's.  Remember you built me two.  One to just show temperature via the microview and then the 2nd was with the added feature of relay control.  I only have been using the relay control code as thats exactly what i want.

Original without relay's


#include <MicroView.h>
#include <OneWire.h> 
int DS18S20_Pin = 2; //DS18S20 Signal pin on digital 2
//Temperature chip i/o
OneWire ds(DS18S20_Pin);  // on digital pin 2
void setup() {
  uView.begin();
}
void loop() {
  float temperature = getTemp() *9/5 + 32;
  if (temperature != -1000) {
    uView.clear(PAGE);
    uView.setFontType(2); // 10 X 16 "seven segment" numeric font
    uView.setCursor(8,15);
    uView.print(temperature, 1); // display with one decimal place
    uView.display();
  }
  delay(1000); //just here to slow down the output so it is easier to read
}
void diplayMessage(const char *message) {
  uView.clear(PAGE);
  uView.setFontType(0); // 5 X 7 font
  uView.setCursor(0,7);
  uView.print(message);
  uView.display();
  delay(2000);
  uView.clear(PAGE);
  uView.display();
  delay(200);
}
float getTemp() {
  //returns the temperature from one DS18S20 in DEG Celsius
  byte data[12];
  byte addr[8];
  if ( !ds.search(addr)) {
      //no more sensors on chain, reset search
      ds.reset_search();
      return -1000;
  }
  if ( OneWire::crc8( addr, 7) != addr[7]) {
      diplayMessage("CRC is\nnot valid!");
      return -1000;
  }
  if ( addr[0] != 0x10 && addr[0] != 0x28) {
      diplayMessage("Device notrecognized");
      return -1000;
  }
  ds.reset();
  ds.select(addr);
  ds.write(0x44,1); // start conversion, with parasite power on at the end
  byte present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE); // Read Scratchpad
  
  for (int i = 0; i < 9; i++) { // we need 9 bytes
    data[i] = ds.read();
  }
  
  ds.reset_search();
  
  byte MSB = data[1];
  byte LSB = data[0];
  float tempRead = ((MSB << 8) | LSB); //using two's compliment
  float TemperatureSum = tempRead / 16;
  
  return TemperatureSum;
}


2nd edition to work with relay's


// MicroView temperature display and thermostat using the
// DS18S20 1-Wire digital thermometer IC
// Based on code from http://bildr.org/2011/07/ds18b20-arduino/
// Original license:
/*
Copyright (c) 2010 bildr community
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// NOTE: The font used to display the temperature doesn't include a
//      minus sign. Only positive temperatures will display properly
//      unless a different font is used.
#include <MicroView.h>
#include <OneWire.h>
// Pin states for heaters
#define HEAT_ON LOW
#define HEAT_OFF HIGH
// Comment out the following line for Celsius 
#define FAHRENHEIT_SCALE
// Turn on heat when the temperature goes below this value
const float HeatOnTemp = 77.5;
// Turn off heat when the temperature goes above this value
const float HeatOffTemp = 79;
// Alert if the temperature goes below this value
const float AlertLowTemp = 76.5;
// Alert if the temperature goes above this value
const float AlertHighTemp = 82;
// Pin assignments
const int DS18S20_Pin = 2; // DS18S20 Signal pin
const int Heater1Pin = 3;  // Heater 1 control
const int Heater2Pin = 5;  // Heater 2 control

boolean heatOn = false; // heat is on when true
OneWire ds(DS18S20_Pin); // Temperature chip i/o
void setup() {
  uView.begin();
  // Set heater pins to outputs and turn them off
  digitalWrite(Heater1Pin, HEAT_OFF);
  pinMode(Heater1Pin, OUTPUT);
  digitalWrite(Heater2Pin, HEAT_OFF);
  pinMode(Heater2Pin, OUTPUT);
}
void loop() {
  float temperature;
  boolean screenFlash = false; // flash the display if set to true
  uView.clear(PAGE);
  temperature = getTemp();
  // A value of -1000 indicates an error.
  // Turn off the heaters and abort the loop.
  if (temperature == -1000) {
    setHeat(HEAT_OFF);
    heatOn = false;
    return;
  }
#ifdef FAHRENHEIT_SCALE
  temperature = temperature * 9/5 + 32;
#endif
  // Display the temperature
  uView.setFontType(2); // 10 X 16 "seven segment" numeric font
  uView.setCursor(8, 13);
  uView.print(temperature, 1); // display with one decimal place
  // Set heaters on or off if required
  if (temperature < HeatOnTemp) {
    heatOn = true;
  }
  else if (temperature > HeatOffTemp) {
    heatOn = false;
  }
  heatControl(heatOn);
  // Set an alert if temperature goes above or below the thresholds
  if (temperature > AlertHighTemp) {
    heatAlert(HIGH);
    screenFlash = true;
  }
  else if (temperature < AlertLowTemp) {
    heatAlert(LOW);
    screenFlash = true;
  }
    
  uView.display(); // Update the screen
  if (screenFlash) { // if necessary, invert the display to cause flashing
    uView.invert(true);
    delay(700);
    uView.invert(false);
    delay (1300);
  }
  else {
    delay(2000);
  }
}
// Set the heat on or off as required and display the current state
void heatControl(boolean on) {
  uView.setFontType(0);
  uView.setCursor(9, 38);
  uView.print("Heat ");
  if (on) {
    uView.print("ON");
    setHeat(HEAT_ON);
  }
  else {
    uView.print("OFF");
    setHeat(HEAT_OFF);
  }
}
// Display a heat alert message
void heatAlert(uint8_t state) {
  uView.setFontType(0);
  if (state == HIGH) {
    uView.setCursor(6, 2);
    uView.print("TOO HIGH!");
  }
  else {
    uView.setCursor(9, 2);
    uView.print("TOO LOW!");
  }
}
// Set the heaters on or off
void setHeat(uint8_t pinState) {
  digitalWrite(Heater1Pin, pinState);
  digitalWrite(Heater2Pin, pinState);
}
// Display a message for a while and then clear the display for
// as short time so a repeated message will flash
void displayMessage(const char *message) {
  uView.setFontType(0); // 5 X 7 font
  uView.setCursor(0,7);
  uView.print(message);
  uView.display();
  delay(2000);
  uView.clear(PAGE);
  uView.display();
  delay(200);
}
// Returns the temperature from one DS18S20 in DEG Celsius
float getTemp() {
  byte data[12];
  byte addr[8];
  if ( !ds.search(addr)) {
    //no more sensors on chain, reset search
    ds.reset_search();
    displayMessage("No sensors");
    return -1000;
  }
  if ( OneWire::crc8( addr, 7) != addr[7]) {
    displayMessage("CRC is\nnot valid!");
    return -1000;
  }
  if ( addr[0] != 0x10 && addr[0] != 0x28) {
    displayMessage("Device notrecognized");
    return -1000;
  }
  ds.reset();
  ds.select(addr);
  ds.write(0x44,1); // start conversion, with parasite power on at the end
  byte present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE); // Read Scratchpad
  for (int i = 0; i < 9; i++) { // we need 9 bytes
    data[i] = ds.read();
  }
  ds.reset_search();
  byte MSB = data[1];
  byte LSB = data[0];
  float tempRead = ((MSB << 8) | LSB); //using two's compliment
  float TemperatureSum = tempRead / 16;
  
  return TemperatureSum;
}



MLXXXp

Avatar / Picture

Senior Member
Registered:
Posts: 75
Reply with quote  #27 
Quote:
Originally Posted by naterad
I am wondering if perhaps we might be looking at different code's.


Look at the getTemp() function in all the programs. That's the code that reads the temperature (in Celsius) from the sensor. Between both my programs and the original code they are all identical except for whitespace for formatting and the error message output. The original also has the added delay, which doesn't seem to affect anything. The error message code won't be executed unless there's an error, which doesn't happen under normal operation. Since getTemp() is the only thing that has to do with what temperature is received from the sensor, in theory, all programs should read the same.

Therefore, assuming the same formula is used to convert from Celsius to Fahrenheit, all three programs should output the same value for a given temperature with the same sensor.

The only other difference is the rate at which the temperature is read from the sensor. My relay control program waits about 2 seconds between readings. The original code reads the sensor continuously without any delay (except the one in the getTemp() function).

Did you try what I suggested earlier, which was to add a delay to the original code? You could also try removing the delay(2000); from the end of loop() in my program.
naterad

Junior Member
Registered:
Posts: 15
Reply with quote  #28 
Well I dont know why its working but it is [frown]  I have spent the last two days reading/learning your code and playing around with delays during conversion and after the getTemp()

The temp is not registering the same as when you load the basic sensor code and watch it via serial which is correct.  It's not until I load your code (relay or not) that its elevated by 1.5-2 degrees.

Below is the code I am using.  The only thing i have changed and only way that I am getting what the serial monitor is reporting is changing the /16 at the very bottom to /5.216.  I do not remember where I got the 5.216 but it was on an old sketch i had years ago with this same sensor when i was playing around with it.


// MicroView temperature display and thermostat using the
// DS18S20 1-Wire digital thermometer IC
// Based on code from http://bildr.org/2011/07/ds18b20-arduino/
// Original license:
/*
Copyright (c) 2010 bildr community
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// NOTE: The font used to display the temperature doesn't include a
//      minus sign. Only positive temperatures will display properly
//      unless a different font is used.
#include <MicroView.h>
#include <OneWire.h>
// Pin states for heaters
#define HEAT_ON LOW
#define HEAT_OFF HIGH
// Comment out the following line for Celsius 
#define FAHRENHEIT_SCALE
// Turn on heat when the temperature goes below this value
const float HeatOnTemp = 80;
// Turn off heat when the temperature goes above this value
const float HeatOffTemp = 81;
// Alert if the temperature goes below this value
const float AlertLowTemp = 79.5;
// Alert if the temperature goes above this value
const float AlertHighTemp = 83;
// Pin assignments
const int DS18S20_Pin = 2; // DS18S20 Signal pin
const int Heater1Pin = 3;  // Heater 1 control
const int Heater2Pin = 5;  // Heater 2 control

boolean heatOn = false; // heat is on when true
OneWire ds(DS18S20_Pin); // Temperature chip i/o
void setup() {
  uView.begin();
  // Set heater pins to outputs and turn them off
  digitalWrite(Heater1Pin, HEAT_OFF);
  pinMode(Heater1Pin, OUTPUT);
  digitalWrite(Heater2Pin, HEAT_OFF);
  pinMode(Heater2Pin, OUTPUT);
}
void loop() {
  float temperature;
  boolean screenFlash = false; // flash the display if set to true
  uView.clear(PAGE);
  // I added this
  Serial.println(temperature);
  temperature = getTemp();
  // A value of -1000 indicates an error.
  // Turn off the heaters and abort the loop.
  if (temperature == -1000) {
    setHeat(HEAT_OFF);
    heatOn = false;
    return;
  }
#ifdef FAHRENHEIT_SCALE
  temperature = temperature ;//*9/5+32;
#endif
  // Display the temperature
  uView.setFontType(2); // 10 X 16 "seven segment" numeric font
  uView.setCursor(8, 13);
  uView.print(temperature, 1); // display with one decimal place
  // Set heaters on or off if required
  if (temperature < HeatOnTemp) {
    heatOn = true;
  }
  else if (temperature > HeatOffTemp) {
    heatOn = false;
  }
  heatControl(heatOn);
  // Set an alert if temperature goes above or below the thresholds
  if (temperature > AlertHighTemp) {
    heatAlert(HIGH);
    screenFlash = true;
  }
  else if (temperature < AlertLowTemp) {
    heatAlert(LOW);
    screenFlash = true;
  }
    
  uView.display(); // Update the screen
  if (screenFlash) { // if necessary, invert the display to cause flashing
    uView.invert(true);
    delay(700);
    uView.invert(false);
    delay (1300);
  }
  else {
    delay(2000);
  }
}
// Set the heat on or off as required and display the current state
void heatControl(boolean on) {
  uView.setFontType(0);
  uView.setCursor(9, 38);
  uView.print("Heat ");
  if (on) {
    uView.print("ON");
    setHeat(HEAT_ON);
  }
  else {
    uView.print("OFF");
    setHeat(HEAT_OFF);
  }
}
// Display a heat alert message
void heatAlert(uint8_t state) {
  uView.setFontType(0);
  if (state == HIGH) {
    uView.setCursor(6, 2);
    uView.print("TOO HIGH!");
  }
  else {
    uView.setCursor(9, 2);
    uView.print("TOO LOW!");
  }
}
// Set the heaters on or off
void setHeat(uint8_t pinState) {
  digitalWrite(Heater1Pin, pinState);
  digitalWrite(Heater2Pin, pinState);
}
// Display a message for a while and then clear the display for
// as short time so a repeated message will flash
void displayMessage(const char *message) {
  uView.setFontType(0); // 5 X 7 font
  uView.setCursor(0,7);
  uView.print(message);
  uView.display();
  delay(2000);
  uView.clear(PAGE);
  uView.display();
  delay(200);
}
// Returns the temperature from one DS18S20 in DEG Celsius
float getTemp() {
  byte data[12];
  byte addr[8];
  if ( !ds.search(addr)) {
    //no more sensors on chain, reset search
    ds.reset_search();
    displayMessage("No sensors");
    return -1000;
  }
  if ( OneWire::crc8( addr, 7) != addr[7]) {
    displayMessage("CRC is\nnot valid!");
    return -1000;
  }
  if ( addr[0] != 0x10 && addr[0] != 0x28) {
    displayMessage("Device notrecognized");
    return -1000;
  }
  ds.reset();
  ds.select(addr);
  ds.write(0x44,1); // start conversion, with parasite power on at the end
  byte present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE); // Read Scratchpad
  for (int i = 0; i < 9; i++) { // we need 9 bytes
    data[i] = ds.read();
  }
  ds.reset_search();
  byte MSB = data[1];
  byte LSB = data[0];
  float tempRead = ((MSB << 8) | LSB); //using two's compliment
  float TemperatureSum = tempRead / 5.216;
  
  return TemperatureSum;
}
MLXXXp

Avatar / Picture

Senior Member
Registered:
Posts: 75
Reply with quote  #29 
Quote:
Originally Posted by naterad
The temp is not registering the same as when you load the basic sensor code and watch it via serial which is correct.  It's not until I load your code (relay or not) that its elevated by 1.5-2 degrees.


Previously you said my code reads 1.5-2 degrees lower than the basic sensor code. Now you're saying it reads 1.5-2 degrees higher. Which one is it?

Quote:
Originally Posted by naterad
Below is the code I am using.  The only thing i have changed and only way that I am getting what the serial monitor is reporting is changing the /16 at the very bottom to /5.216.


No, your code also disables the *9/5+32 code for converting from Celsius to Fahrenheit.

Again, I suggest you try putting your sensor in some ice water using your current code and compare it with what your lab grade chemistry thermometer reads in the same water.


Previous Topic | Next Topic
Print
Reply

Quick Navigation:


Create your own forum with Website Toolbox!