Go Down

Topic: 1 Wire DS18B20 Minimal Coding (Read 1 time) previous topic - next topic

transcendtient

Jun 07, 2013, 07:44 pm Last Edit: Jun 09, 2013, 08:19 am by transcendtient Reason: 1
I'm working on paring a sketch for space as I'm placing it on an ATTiny45, and so I've been deleting code left and right, replacing function calls with hard coded data.

Also... the data byte array in the example says it needs 9 bytes, but it only utilizes 2? I chopped it down to a 2 byte array and it worked, but I don't know if I'm somehow wrong for doing that.

One more thing... when I first plug in my sensor (doesn't happen when it's simply reset) I get a junk reading of 185.0f for my first reading. Not a big problem, but annoying.

I've come to the point where I'm not sure I can do any more. Help me chop!
Here is the getTemp function:
Code: [Select]
float getTemp(){
  resetDS();
  writeByte(0x44); // start conversion, without parasite power on at the end
 
  resetDS();
  writeByte(0xBE); // Read Scratchpad
 
  return (readByte()|(readByte() << 8))*0.1125+32;//convert to deg f
}

void resetDS()
{
  pinMode(DS18S20_Pin, OUTPUT);
  digitalWrite(DS18S20_Pin, LOW);
  delayMicroseconds(255);//480u reqd
  pinMode(DS18S20_Pin, INPUT);
  delayMicroseconds(255);//480u reqd
  writeByte(0xCC);//ROM skip as only one sensor
}

void writeByte(byte data){
  pinMode(DS18S20_Pin, OUTPUT);
  for (byte mask = 00000001; mask>0; mask <<= 1){
    if (data & mask ){ // send 1
      digitalWrite(DS18S20_Pin,LOW);
      delayMicroseconds(10);//15u reqd
      digitalWrite(DS18S20_Pin,HIGH);
      delayMicroseconds(45);//60u total
    }
    else{ //if bitwise and resolves to false
      digitalWrite(DS18S20_Pin,LOW); // send 0
      delayMicroseconds(50);
      digitalWrite(DS18S20_Pin,HIGH);
      //delayMicroseconds(5);//60u total is slow enough to negate needing this
    }
  }
}

byte readByte(){
  byte r = 0;
  for (byte mask = 00000001; mask>0; mask <<= 1){
    pinMode(DS18S20_Pin, OUTPUT);
    digitalWrite(DS18S20_Pin, LOW);
    //delayMicroseconds(3);//1u reqd pinMode() is slow enough to negate needing this
    pinMode(DS18S20_Pin, INPUT); // let pin float, pull up will raise
    delayMicroseconds(10);//15u reqd
    if(digitalRead(DS18S20_Pin))r|=mask;
    delayMicroseconds(40);//60u complete cycle
  }
  return r;
}


Here is the rest of the program...
Code: [Select]
#include <SPI.h>
#include <MyLiquidCrystal.h>
int DS18S20_Pin = 5; //DS18S20 thermometer pin*/

byte heatingStage=0;

const int q0 = 1;//first unused 74HC595 pin
const int q2 = 4;//second unused 74HC595 pin

LiquidCrystal lcd(0);// initialize LCD with the number of the ss/latch
     
void setup() { 
  lcd.begin(16, 2);// set up the LCD's number of columns and rows:
}
     
void loop() {
  noInterrupts();
  float temperature = getTemp();//temperature data
  interrupts();
  lcd.setCursor(0,0);
  lcd.print("Temp: ");
  lcd.print(temperature,1);
  lcd.print("f"); 
 
  if(temperature < 72 && heatingStage!=q0+q2){//stage two heating
    lcd._bitString=heatingStage=q0+q2;
    lcd.spiSendOut();
    lcd.setCursor(0,1);
    lcd.print("Stage 2 Heating ");
  }
  if(temperature < 78 && temperature > 72 && heatingStage!=q0){//stage one heating
    lcd._bitString=heatingStage=q0;
    lcd.spiSendOut();
    lcd.setCursor(0,1);
    lcd.print("Stage 1 Heating"); 
  } 
  if(temperature > 78){//heat off
    lcd._bitString=heatingStage=0;
    lcd.spiSendOut();
    lcd.setCursor(0,1);
    lcd.print("Heating Off    ");
  }
}

johnwasser

If there is only one device on the OneWire bus you can tell it to respond without requiring an address. That would eliminate the address array.
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

transcendtient

That did get me quite a bit, I appreciate it.
I've switched my code over to an SPI variant as the library code is smaller and easier to rummage through, and I'm exploring the possibility of adding an SD to log my temperature.
I'm still interested in any other size reductions anyone has.

Nick_Pyner

Some your code alludes to the DS18S20. I don't know what the difference is, if any, but, if you are using just one DS18B20, I don't think it makes any sense to use the standard procedures for multiple devices.  You don't need any of that address stuff, and you don't need the one wire library.

You might find the code below useful. Strip out the stuff you don't need - which is most of it. It is actually written for two DS18B20s. Not a good idea, and the product of a comedy of errors.

Code: [Select]


#define tture1 14//no ; here
#define tture2 15//no ; here

// include the library codes:
#include <LiquidCrystal.h>
#include <SD.h>

File myFile;

// initialize the library with the numbers of MY interface pins
LiquidCrystal lcd(8,9,16,5,6,7);

int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;

void setup() {
    //For each tture sensor: Do a pinMode and a digitalWrite
    pinMode(tture1, INPUT);
    pinMode(tture2, INPUT);

    digitalWrite(tture1, LOW);//Disable internal pull-up.
    digitalWrite(tture2, LOW);

    Serial.begin(9600);
    delay(300);//Wait for newly restarted system to stabilize
    Serial.print("Temperature measurement, two sensors:\n\n");

  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  lcd.clear();
  // Print a message to the LCD.
  lcd.print("temp   in   out");   
 
  Serial.print("Initializing SD card...");

   pinMode(10, OUTPUT);
   
  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
 
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  myFile = SD.open("test.txt", FILE_WRITE);//+++++++++++++++++++ OPEN
 
  // if the file opened okay, write to it:
  if (myFile) {
    Serial.print("Writing to test.txt...");
    myFile.println("testing! Did you forget the date?");
    myFile.close();//++++++++++++++++++++++++++++++++++++++++++++ CLOSE

    Serial.println("done.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
 
}

void loop(){

// set the LCD cursor to column 4, line 1
  // (note: line 1 is the second row, since counting begins with 0):
  lcd.setCursor(4, 1);
  readTture(tture1);//N.B.: Values passed back in globals
  printTture();//N.B.: Takes values from globals. Also...
     //no newline part of printTture;

  delay(120);// Delay... must not be too short.
 
  // set LCD cursor for second temp
  lcd.setCursor(11, 1);
  readTture(tture2);//Now read and report 2nd tture.
  printTture();
  delay(200);// Delay... must not be too short.
  Serial.print("\n");//Start new line
 
       myFile = SD.open("test.txt", FILE_WRITE);//+++++++++++++++++++++++++OPEN
       myFile.println(",   ");
    myFile.close();//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>CLOSE
  delay(880);
}


void OneWireReset(int Pin) // reset.  Should improve to act as a presence pulse
{
     digitalWrite(Pin, LOW);
     pinMode(Pin, OUTPUT); // bring low for 500 us
     delayMicroseconds(500);
     pinMode(Pin, INPUT);
     delayMicroseconds(500);
}
//end OneWireReset

void OneWireOutByte(int Pin, byte d) // output byte d (least sig bit first).
{
   byte n;

   for(n=8; n!=0; n--)
   {
      if ((d & 0x01) == 1)  // test least sig bit
      {
         digitalWrite(Pin, LOW);
         pinMode(Pin, OUTPUT);
         delayMicroseconds(5);
         pinMode(Pin, INPUT);
         delayMicroseconds(60);
      }
      else
      {
         digitalWrite(Pin, LOW);
         pinMode(Pin, OUTPUT);
         delayMicroseconds(60);
         pinMode(Pin, INPUT);
      }
      d=d>>1; // now the next bit is in the least sig bit position.
   }
}//end OneWireOutByte

byte OneWireInByte(int Pin) // read byte, least sig byte first
{
    byte d, n, b;

    for (n=0; n<8; n++)
    {
        digitalWrite(Pin, LOW);
        pinMode(Pin, OUTPUT);
        delayMicroseconds(5);
        pinMode(Pin, INPUT);
        delayMicroseconds(5);
        b = digitalRead(Pin);
        delayMicroseconds(50);
        d = (d >> 1) | (b<<7); // shift d to right and insert b in most sig bit position
    }
    return(d);
}//end OneWireInByte

void readTture(byte Pin){
//Pass WHICH pin you want to read in "Pin"
//Returns values in... (See global declarations)
  OneWireReset(Pin);
  OneWireOutByte(Pin, 0xcc);
  OneWireOutByte(Pin, 0x44); // perform temperature conversion, strong pullup for one sec

  OneWireReset(Pin);
  OneWireOutByte(Pin, 0xcc);
  OneWireOutByte(Pin, 0xbe);

  LowByte = OneWireInByte(Pin);
  HighByte = OneWireInByte(Pin);
  TReading = (HighByte << 8) + LowByte;
  SignBit = TReading & 0x8000;  // test most sig bit
  if (SignBit) // negative
  {
    TReading = (TReading ^ 0xffff) + 1; // 2's comp
  }
  Tc_100 = (6 * TReading) + TReading / 4;    // multiply by (100 * 0.0625) or 6.25

  Whole = Tc_100 / 100;  // separate off the whole and fractional portions
  Fract = Tc_100 % 100;
};//end readTture

void printTture(){//Uses values from global variables.
//See global declarations.
//N.B.: No new line inside printTture
      myFile = SD.open("test.txt", FILE_WRITE); //+++++++++++++OPEN
if (SignBit) // If it's negative
    {
     Serial.print("-");
     lcd.print("-");

     myFile.print("-");
    };
  Serial.print(Whole);
  Serial.print(".");
  lcd.print(Whole);
  lcd.print(".");
  myFile.print(Whole);
  myFile.print(".");
  if (Fract < 10)
    {
     Serial.print("0");
     lcd.print("0");
     myFile.print("0");
    };
  Serial.print(Fract);
  lcd.print(Fract);
  myFile.print(Fract);
    Serial.print("       ");
    myFile.print(",    ");
  myFile.close();//++++++++++++++++++++++++ CLOSE
};//end printTture



transcendtient

I have it down to the three functions
ds.reset()
ds.write()
ds.read()

I'm in the process of combing through those functions in the OneWire library to reduce their footprint.

Go Up