dallas 1-wire problem (Læst 4771x)

Offline martinbjerre

  • Jordet Basic
  • **
  • Indlæg: 151
  • Antal brugbare Indlæg: 10
    • Vis profil
dallas 1-wire problem
« Dato: Januar 25, 2016, 19:54:48 »
Jeg har købt ny campingvogn, og nu går der nørd i det ;)
Til at styre varmen hjemmefra (inden vi kører ud til vognen) har jeg sakset og redigeret nedenstående.
Spørgsmålet er hvordan jeg finder adressen på min føler, eller får skidtet til at fungere uden at kende adressen.
Føleren er selvfølgelig monteret i vognen, så den er ikke lige til at pille ud....
Kode:
/*
 * Halfluck Temperature Controller Webserver
 * An open-source Temperature Controller for Arduino.
 * v1.4 23/7/2012
 * Hosted at http://www.halfluck.com/source/webserver/TempControllerWebServer.ino
 * Described in http://www.halfluck.com/source/webserver/TempControllerWebServer.ino
 *
 * TempControllerWebServer.ino
 *
 * (cc) by Rob Hart
 *
 * http://www.halfluck.com
 * http://creativecommons.org/license/cc-gpl
 *targettemp
 * Compiled & Tested in Arduino 1.0.1
 * using OneWire Library v2.1 http://www.arduino.cc/playground/Learning/OneWire
 * using Ethercard Library https://github.com/jcw/ethercard/
 *
 */

#include <EtherCard.h>
#include <OneWire.h>
#include <EEPROM.h>

char TargetTemperarureTextbox[10];            // Data in text box

// ethernet interface mac address, must be unique on the LAN
static byte mymac[] = {
  0x10,0x4a,0x7d,0x90,0xd3,0xa0 };
static byte myip[] = {
  192,168,0,111 }; //used for static IP

byte Ethernet::buffer[1000]; // if you increase the size of the HTML
// code you may need to increase the buffer size
// (or it will stop working) //TODO
BufferFiller bfill;

const byte PinTemp = 4;    // Dallas Ds1820 Temperature Sensors
const byte PinSSR1 = 5;    // Pin for SSR 1
const byte PinSSR2 = 6;    // Pin for SSR 2

byte sensor1[8] = {
  0x28, 0x61, 0x24, 0xC5, 0x03, 0x00, 0x00, 0x51}; 
// User Defined Temperature Sensor Address 1
int currenttemp1 = 0;     // curent temperature (1/16th degrees) sensor1
int lasttemp1    = 0;     // previous temperature sensor 1
byte negativetemp1 = 0;   // if negative temp display that
byte fractlessthan10 = 0; // if less than 10 then add a zero first

int SignBit, Whole, Fract, Tc_100;
byte TargetTemp = 0;      // this is the placeholder for the target temperature
byte currenttemp1byte = 0;
OneWire ds(PinTemp);

byte Mode = 0;  // 0 is Manual, 1 is Auto
byte SSR1on = 0;  // 0 is Off, 1 is On
byte SSR2on = 0;  // 0 is Off, 1 is On

void setup () {
  if (ether.begin(sizeof Ethernet::buffer, mymac, 10) == 0);
  //Add alternative begin with 3rd parameter to specify CS pin to use.
  // Only 8, 9 and 10 are usable. Default without 3rd parameter is pin 8.
  ether.staticSetup(myip);
  pinMode(PinTemp, INPUT);          // sets the digital pin as input
  pinMode(PinSSR1, OUTPUT);          // sets the digital pin as input
  pinMode(PinSSR2, OUTPUT);          // sets the digital pin as input

  TargetTemp = EEPROM.read(0);
  Mode = EEPROM.read(1);

  //  //Stuff for DHCP
  //  Serial.begin(57600);
  //  Serial.println("\nDHCP]");
  // 
  //  if (ether.begin(sizeof Ethernet::buffer, mymac, 10) == 0)
  //    Serial.println( "Failed to access Ethernet controller");
  //
  //  Serial.println("Setting up DHCP");
  //  if (!ether.dhcpSetup())
  //    Serial.println( "DHCP failed");
  // 
  //  ether.printIp("My IP: ", ether.myip);
  //  ether.printIp("Netmask: ", ether.mymask);
  //  ether.printIp("GW IP: ", ether.gwip);
  //  ether.printIp("DNS IP: ", ether.dnsip);

}

int tempread(byte sensoraddr[])
// error codes:
// -1 no sensors found
// -2 invalid CRC
// -3 not a DS1820
{
  byte i;
  byte present = 0;
  byte data[12];
  byte addr[8];
  //int HighByte, LowByte, TReading, SignBit, Tc_100, Tf_100, Whole, Fract;
  int Temp;

  if ( !ds.search(addr)) {
    ds.reset_search();
    return -1;
  }

  if ( OneWire::crc8( addr, 7) != addr[7]) {
    return -2;
  }

  if ( addr[0] != 0x28) {
    return -3;
  }

  for ( i = 0; i < 8; i++) {
    addr[i]=sensoraddr[i];
  }
  ds.reset(); // pulse the pins and wait for a response to reset the DS1820
  ds.select(addr); // 0x55 (MATCH_ROM) followed by the address of the 1820 to talk to.
  //  ds.write(0x44,1); // start conversion, with parasite power on at the end

  ds.write(0x44,0);  //PARASITE POWER OFF
  //delay(800);     

  present = ds.reset();
  ds.select(addr);   
  ds.write(0xBE);    // Read Scratchpad

  for ( i = 0; i < 9; i++) {      // we need 9 bytes
    data[i] = ds.read();

  }
  Temp=(data[1]<<8)+data[0]; //take the two bytes response holding temperature

  SignBit = Temp & 0x8000;  // test most sig bit
  if (SignBit) // negative
  {
    Temp = (Temp ^ 0xffff) + 1; // 2's comp
  }

  return Temp;
}

const char http_OK[] PROGMEM =
"HTTP/1.0 200 OK\r\n"
"Content-Type: text/html\r\n"
"Pragma: no-cache\r\n\r\n";

const char http_Found[] PROGMEM =
"HTTP/1.0 302 Found\r\n"
"Location: /\r\n\r\n";

const char http_Unauthorized[] PROGMEM =
"HTTP/1.0 401 Unauthorized\r\n"
"Content-Type: text/html\r\n\r\n"
"<h1>401 Unauthorized</h1>";

static word homePage() {

  // bfill = ether.tcpOffset();

  //$D = word data type
  //$L = long data type
  //$S = c string
  //$F = progmem string
  //$E = byte from the eeprom.
  //Uptime Stuff
  long days=0;
  long hours=0;
  long mins=0;
  long secs=0;
  secs = millis()/1000; //convect milliseconds to seconds
  mins=secs/60; //convert seconds to minutes
  hours=mins/60; //convert minutes to hours
  days=hours/24; //convert hours to days
  secs=secs-(mins*60); //subtract the coverted seconds to minutes in order to display 59 secs max
  mins=mins-(hours*60); //subtract the coverted minutes to hours in order to display 59 minutes max
  hours=hours-(days*24); //subtract the coverted hours to days in order to display 23 hours max

  char* SSR1stat;
  if ( digitalRead(PinSSR1) == HIGH ) {
    SSR1stat = "On" ;
  }
  else {
    SSR1stat = "Off";
  }

  char* SSR2stat;
  if ( digitalRead(PinSSR2) == HIGH ) {
    SSR2stat = "On" ;
  }
  else {
    SSR2stat = "Off";
  }

  if (Mode == 0) //If Manual
  {
    bfill.emit_p(PSTR(
    "HTTP/1.0 200 OK\r\n"
      "Content-Type: text/html\r\n"
      "Pragma: no-cache\r\n"
      "\r\n"
      "<!DOCTYPE html>"
      "<html><head>"
      "<meta http-equiv='refresh' content='5'/>"
      "<title>Adria Webserver</title>"
      "<body bgcolor=""#99CCFF"">"
      "<center>"
      "<hr />"
      "<br />"
     "<font size=""5"">"
      "Martin`s campingvogn <b>"
      "<br />"
      "Temperatur i vognen: <b>"
      "<br />"
      "<br />"
      "<font size=""7"">"
      "$D.$D &deg;C</font></b>"   
      "<br />"
      "<br />"
      "<font size=""5"">"
      "Varme er <b>$S</b> "
      "<form><input type=""button"" value=""Skift"" "
      "onClick=""document.location.href='/?SSR1toggle';""></form>"
      "<br />"
      "Gulvvarme er <b>$S</b> "
      "<form><input type=""button"" value=""Skift"" "
      "onClick=""document.location.href='/?SSR2toggle';""></form>"
      "<br />"
      "<br />"
      "<form><input type=""button"" value=""Skift&nbsp;til&nbsp;"
      "Auto"" onClick=""document.location.href='/?modeauto';""></form>"   
      "<hr />"
      "Uptime: $L Days $L Hours $L Mins $L Secs"
      "</center></body></html>"),
    Whole , Fract , SSR1stat, SSR2stat, days, hours, mins, secs );
    return bfill.position();
  }
  else  //its AutoMode display Target Temp
  // and Textbox for adjusting Temperature
  {
    bfill.emit_p(PSTR(
    "HTTP/1.0 200 OK\r\n"
      "Content-Type: text/html\r\n"
      "Pragma: no-cache\r\n"
      "\r\n"
      "<!DOCTYPE html>"
      "<html><head>"
      "<meta http-equiv='refresh' content='5'/>"
      "<title>Adria Webserver</title>"
      "<body bgcolor=""#99CCFF"">"
      "<center>"
      "<hr />"
      "<br />"
      "<font size=""5"">"
      "Martin`s campingvogn <b>"
      "<br />"
      "Temperatur i vognen: <b>"
      "<br />"
      "<br />"
      "<font size=""7"">"
      "$D.$D &deg;C</font></b>"   
      "<br />"
      "<br />"
      "<font size=""5"">"
      "Auto Temperatur: <b>"
      "$D.0 &deg;C</b>"
      "<br />"
      "<br />"
      "Varme er <b>$S</b> "
      "<br />"
      "<br />"
    //  "Pump is <b>$S</b> "
    //     "<br />"
    //    "<form>"
    //    "<select id=""setit"" name=""select"">"
    //    "<option value=""/?modemanual"">Switch to Manual</option>"
    //    "</select>"
    //    "<input type=""button"" value=""Ok"" "
    //    "onclick=""window.open((setit.options[setit.selectedIndex].value)"
    //    ",'_self')""></form>"
    "Skift Auto Temp"
      "<form><input type=text name=targettemp size=10>"
      "<input type=submit value=Ok> </form>"
      "<br />"
      "<form><input type=""button"" value=""Skift&nbsp;til&nbsp;Manuel"" "
      "onClick=""document.location.href='/?modemanual';""></form>" 
      "<hr />"
      "Uptime: $L Days $L Hours $L Mins $L Secs"
      "</center></body></html>"),
    //Whole , Fract , TargetTemp, SSR1stat, SSR2stat, days, hours, mins, secs );
    Whole , Fract , TargetTemp, SSR1stat, days, hours, mins, secs );
    return bfill.position();
  }       
}

void loop () {


  if (Mode == 1) //if auto mode
  {
    if ((currenttemp1byte<TargetTemp) &&
      (currenttemp1byte>0)) // below low range
    {
      digitalWrite(PinSSR1, HIGH);       // turn SSR1oning on
      SSR1on = 1;
    }
    else if ((currenttemp1byte>=TargetTemp) &&
      (currenttemp1byte>0)) //ideal range
    {
      digitalWrite(PinSSR1, LOW);       // turn SSR1oning off
      SSR1on = 0;
    }
  }
  currenttemp1 = tempread(sensor1);
  if (currenttemp1>0)
  {
    currenttemp1byte = (byte)(currenttemp1>>4);
  }
  else {
    currenttemp1byte = 0;
  }

  if ((currenttemp1 != lasttemp1) && (currenttemp1>0))
  {
    Tc_100 = (6 * currenttemp1) + currenttemp1 / 4;
    // multiply by (100 * 0.0625) or 6.25
    //   Tf_100 = ((1.8)*Tc_100) + (32*100); // Farenheit
    Whole = Tc_100 / 100;  // separate off whole and fractional portions
    Fract = Tc_100 % 100;
    if (SignBit) // If its negative //TODO
    {
      negativetemp1 = 1;
    }
    else
    {
      negativetemp1 = 0;
    }
    if (Fract < 10) //TODO
    {
      fractlessthan10 = 1;
    }
    else
    {
      fractlessthan10 = 0;
    }
    lasttemp1 = currenttemp1;
  }

  word len = ether.packetReceive();
  word pos = ether.packetLoop(len);

  if (pos) {
    // write to LED digital output

    delay(1);   // necessary for my system //TODO
    bfill = ether.tcpOffset();
    char *data = (char *) Ethernet::buffer + pos;
    if (strncmp("GET /", data, 5) != 0) {
      // Unsupported HTTP request
      // 304 or 501 response would be more appropriate
      bfill.emit_p(http_Unauthorized);
    }
    else {
      data += 5;

      if (data[0] == ' ') {
        // Return home page
        homePage();
      }
      else if (strncmp( "?modeauto" , data, 9 ) == 0)
      {
        Mode = 1;
        EEPROM.write(1, Mode);
        digitalWrite(PinSSR1, LOW);       // turn SSR1 off
        SSR1on = 0;    // switch SSR off       
        digitalWrite(PinSSR2, LOW);       // turn SSR1 off
        bfill.emit_p(http_Found);
      }
      else if (strncmp( "?modemanual" , data, 11 ) == 0)
      {
        Mode = 0;
        SSR1on = 0;    // switch SSR off       
        EEPROM.write(1, Mode);
        digitalWrite(PinSSR1, LOW);       // turn SSR1 off
        digitalWrite(PinSSR2, LOW);       // turn SSR1 off
        bfill.emit_p(http_Found);
      }

      else if (strncmp( "?SSR1toggle" , data, 11 ) == 0)
      {
        if (SSR1on == 0)
        {
          SSR1on = 1; // switch SSR off   
          digitalWrite(PinSSR1, HIGH);       // turn SSR1 off
        }
        else
        {
          SSR1on = 0; // switch SSR off   
          digitalWrite(PinSSR1, LOW);       // turn SSR1 off
        }
        bfill.emit_p(http_Found);
      }         

      else if (strncmp( "?SSR2toggle" , data, 11 ) == 0)
      {
        if (SSR2on == 0)
        {
          SSR2on = 1; // switch SSR off   
          digitalWrite(PinSSR2, HIGH);       // turn SSR1 off
        }
        else
        {
          SSR2on = 0; // switch SSR off   
          digitalWrite(PinSSR2, LOW);       // turn SSR1 off
        }
        bfill.emit_p(http_Found);
      }

      else if (strncmp( "?targettemp=" , data , 12 ) == 0)
      {
        if (ether.findKeyVal(data+1, TargetTemperarureTextbox,
        sizeof TargetTemperarureTextbox , "targettemp") > 0)
        {
          byte value = atoi(TargetTemperarureTextbox);   
          // command to convert a string to number
          if ((value >=0) && (value <=25))  // temp within 0-25 range
          {
            TargetTemp = value;
            EEPROM.write(0, value);
          }
        }
        bfill.emit_p(http_Found);
      }
      ether.httpServerReply(bfill.position());
    }
  }
} //loop()
« Senest Redigeret: Januar 25, 2016, 19:58:18 af martinbjerre »

 

Offline Jakobsen

  • Højpas filter
  • *****
  • Indlæg: 302
  • Antal brugbare Indlæg: 45
    • Vis profil
Sv: dallas 1-wire problem
« Svar #1 Dato: Januar 25, 2016, 22:23:33 »
Citér
Spørgsmålet er hvordan jeg finder adressen på min føler, eller får skidtet til at fungere uden at kende adressen.

Mener du 1-Wire ID nummeret (ROM) eller IP adresse?

Hvis man kun har en device på en 1-Wire kan man normal lade være med at benytte ID nummeret (ROM), men det går jo ikke hvis man har flere devices på samme ledning  :o

Der er flere programmer der kan scanne en 1-Wire bus og fortælle hvilke devices og ID numre (ROM) der er forbundet.

Det nemmeste er at skippe ROM check hvis du kun har en DS1820 forbundet

Se pdf på side 18 "DS18S20 Operation Example 2"
https://datasheets.maximintegrated.com/en/ds/DS18S20.pdf
Databadet er godt nok på DS18S20 og ikke DS1820 som er udgået ... hvilken en har du?

http://playground.arduino.cc/Learning/OneWire her er masser af info på 1-Wire og Arduino, blot til inspiration  :)

 

Offline martinbjerre

  • Jordet Basic
  • **
  • Indlæg: 151
  • Antal brugbare Indlæg: 10
    • Vis profil
Sv: dallas 1-wire problem
« Svar #2 Dato: Januar 26, 2016, 06:20:38 »
Jeg bruger en 18B20.
I linie 43 burde jeg jo indsætte adressen på min føler, men eftersom jeg kun har 1, burde det ikke være nødvendigt. Jeg har prøvet, men jeg får ingen temperaturværdi, og jeg tror det er fordi der står en forkert adresse i programmet.
Som jeg ser det, er der 2 muligheder:
Enten skiller jeg vognen ad, piller føleren ud så jeg kan få udlæst adressen.
Ellers skal programmet modificeres, så det ikke er nødvendigt med en adresse.

 

Offline Jakobsen

  • Højpas filter
  • *****
  • Indlæg: 302
  • Antal brugbare Indlæg: 45
    • Vis profil
Sv: dallas 1-wire problem
« Svar #3 Dato: Januar 26, 2016, 12:02:41 »
Citér
Ellers skal programmet modificeres, så det ikke er nødvendigt med en adresse.
Det er ikke nødvendigt med adressen  :) , men du kan ikke bare sætte en tilfældig adresse ind i linie 43 det vil ikke virke, så du må enten læse den med software eller benytte "SKIP ROM [CCh]" funktionen

pdf på den føler du har http://datasheets.maximintegrated.com/en/ds/DS18B20.pdf
Der er beskrevet udførligt hvordan man læser med "SKIP ROM [CCh]" side 18

btw... familie kode er 0x28 for DS1820, DS18B20 men ikke for DS18S20 den er 0x10

Prøv at se denne kode den er meget simpel og benytte stadig ID men læser den selv
http://bildr.org/?s=ds18b20

 

Offline Danni-Hansen

  • µProcessoren
  • *
  • Indlæg: 544
  • Antal brugbare Indlæg: 17
    • Vis profil
Sv: dallas 1-wire problem
« Svar #4 Dato: Januar 26, 2016, 23:44:59 »
Mvh. Danni Hansen.

 

Offline Danni-Hansen

  • µProcessoren
  • *
  • Indlæg: 544
  • Antal brugbare Indlæg: 17
    • Vis profil
Sv: dallas 1-wire problem
« Svar #5 Dato: Januar 26, 2016, 23:50:42 »
Du kan enda finde nogle projekter her inde om emnet.

I denne tråd benyttes der også et nokia display.
http://elektronik-forum.dk/index.php?topic=886.msg5228
Mvh. Danni Hansen.