ATtiny85 DS18B20: Difference between revisions

From wikipost
Jump to navigation Jump to search
No edit summary
No edit summary
 
Line 5: Line 5:
/*
/*



DS18B20 code for DigiStump (ATtiny85) programmed with Arduino
DS18B20 code for DigiSpark (ATtiny85) programmed with Arduino


- board manager url: http://digistump.com/package_digistump_index.json
- board manager url: http://digistump.com/package_digistump_index.json

- board: Digispark Default (16.5MHz)
- programmer: Micronucleus
- programmer: Micronucleus


NOTE: the digispark board requires re-insertion in a USB socket every time you wish to upload code to it.


This code does not rely on any external OneWire or DallasTemperature sensor libraries.
This code does not rely on any external OneWire or DallasTemperature sensor libraries.
Line 21: Line 26:
-------------------------
-------------------------






DS18S20
DS18S20
Line 55: Line 57:




*/
*/




Line 64: Line 66:
#define THERM_DDR DDRB
#define THERM_DDR DDRB
#define THERM_PIN PINB
#define THERM_PIN PINB
#define THERM_DQ PB2 // Define DS1820 DQ pin
#define THERM_DQ PB0 // Define DS1820 DQ pin

#define LEDPIN PB1 // built-in LED is on PB1 (Digispark Model A)


#define THERM_INPUT_MODE() THERM_DDR&=~(1<<THERM_DQ)
#define THERM_INPUT_MODE() THERM_DDR&=~(1<<THERM_DQ)
Line 108: Line 112:
{
{
//Serial.begin(9600);
}
}
Line 143: Line 147:
}
}
}
}


void singleBlink()
{
pMode(LEDPIN,OUTPUT);
dWrite(LEDPIN,HIGH);
_delay_ms(50);
dWrite(LEDPIN,LOW);
_delay_ms(500);
}

void nrBlinker(int nr)
{

if (nr < 100)
for (int i=int(nr/10); i>0; i--)
singleBlink(); // blink tens

nr = nr - (int) (nr / 10) * 10;
delay(1000);

if (nr < 10)
for (int i=nr; i>0; i--)
singleBlink(); // blink ones

}




Line 503: Line 533:
//Serial.print(" C");
//Serial.print(" C");
nrBlinker(digit);
_delay_ms(1000);


// decimals are stored as a 4-digit positive number (e.g. 3625), scale back to < 100
//Serial.println();
decimal = (int) (decimal / 100);
nrBlinker(decimal);
_delay_ms(1000);
_delay_ms(1000);
_delay_ms(1000);


Line 520: Line 554:


}
}





Line 526: Line 561:
{
{
uint8_t ack;
int devs;


uint8_t ack;
int devs;
while (1)
while (1)
{
{



ack = owReset(THERM_DQ);
ack = owReset(THERM_DQ);
Line 540: Line 573:
{
{


//Serial.println("no sensors found");
// no sensors found
_delay_ms(1000);
nrBlinker(2);


} else {
} else {


// sensor activity detected
// sensor activity detected
while (1)
{


devs=scanbus(); // detect and store device rom's in an array
devs=scanbus(); // detect and store device rom's in an array
if (devs > 0)
if (devs > 0)
{
{
_delay_ms(1000);
_delay_ms(1000);
_delay_ms(1000);
_delay_ms(1000);
showdevs();


} else {
showdevs();


//Serial.print(devs);
} else {
//Serial.println(" sensors found");
}

_delay_ms(1000);
_delay_ms(1000);
_delay_ms(1000);
_delay_ms(1000);


// unable to get sensible data back from sensors
}
}


}


_delay_ms(1000);
_delay_ms(1000);
_delay_ms(1000);
_delay_ms(1000);



}


_delay_ms(1000);
_delay_ms(1000);
_delay_ms(1000);
_delay_ms(1000);

}
}




}
}
</pre>
</pre>

Latest revision as of 01:49, 27 December 2021



/*


  DS18B20 code for DigiSpark (ATtiny85) programmed with Arduino

   - board manager url: http://digistump.com/package_digistump_index.json 

   - board: Digispark Default (16.5MHz)
   
   - programmer: Micronucleus

  
  NOTE: the digispark board requires re-insertion in a USB socket every time you wish to upload code to it.

   
  
  This code does not rely on any external OneWire or DallasTemperature sensor libraries.

 
  
   DS18B20 temperature sensor
   -------------------------


           DS18S20

           byte 1                 byte 2
           -------------------------------
           76543210             76543210
           00101010             00000000
           IIIIDDDD             SSSSSIII 
           3210                      654 

           I = Celsius integer digits (signed)          000 0010 = 2
           D = Number of decimal steps (x multiplier)   1010     = 10 steps x 0.0625
           S = Signedness (0=positive, 1=negative)      00000    = +
   

           DS1820

           LSB (1st 7 bits are the temperature)
           and the last bit represents .0 or .5 degrees

           Example:   '87654321'
                       TTTTTTTH
           
             T = Temperature
             H = halves H=0 (.0), H=1 (.5)

           MSB (is 0 when positive, 1 when negative) 




*/


#include <avr/io.h>
#include <util/delay.h>

#define THERM_PORT   PORTB
#define THERM_DDR    DDRB
#define THERM_PIN    PINB
#define THERM_DQ     PB0  // Define DS1820 DQ pin

#define LEDPIN  PB1  // built-in LED is on PB1 (Digispark Model A)

#define THERM_INPUT_MODE()    THERM_DDR&=~(1<<THERM_DQ)
#define THERM_OUTPUT_MODE()   THERM_DDR|=(1<<THERM_DQ)
#define THERM_LOW()           THERM_PORT&=~(1<<THERM_DQ)
#define THERM_HIGH()          THERM_PORT|=(1<<THERM_DQ)

#define HIGH   1
#define LOW    0
#define INPUT  1 
#define OUTPUT 0

#define THERM_CMD_CONVERTTEMP    0x44
#define THERM_CMD_RSCRATCHPAD    0xbe
#define THERM_CMD_WSCRATCHPAD    0x4e
#define THERM_CMD_CPYSCRATCHPAD  0x48
#define THERM_CMD_RECEEPROM      0xb8
#define THERM_CMD_RPWRSUPPLY     0xb4
#define THERM_CMD_SEARCHROM      0xf0
#define THERM_CMD_READROM        0x33
#define THERM_CMD_MATCHROM       0x55
#define THERM_CMD_SKIPROM        0xcc
#define THERM_CMD_ALARMSEARCH    0xec

#define THERM_DECIMAL_STEPS_12BIT   625    // 0.0625, for 12-bit accuracy

#define PRESENCE_ERR 0xFF
#define DATA_ERR     0xFF
#define LAST_DEVICE  0x00
#define SEARCH_FIRST 0xFF

#define CLEAR(s) memset(&(s), 0, sizeof(s))     // to clear an array


int      got_ack;
uint8_t  romcodes[20][9];  // store romcode of 20 sensors max
uint8_t  scratchpad[9];    // stores a scratchpad

char buffer[16];


void setup() 
{
  
  
   
}


void pMode(int pin,int state)
{ 
  if (state == OUTPUT)
  {
    (DDRB |= (1 << pin)); 
  } else { 
    (DDRB &= ~(1 << pin)); 
  }
} 

void dWrite(int pin, int state)
{
  if (state == HIGH)
  { 
    (PORTB |= (1 << pin)); 
  } else {
    (PORTB &= ~(1 << pin));
  }
} 


int dRead(int pin)
{ 
  if (bit_is_set(PINB,pin))
  {
    return 1; 
  } else { 
    return 0; 
  }
} 


void singleBlink()
{
  pMode(LEDPIN,OUTPUT);
  dWrite(LEDPIN,HIGH);
  _delay_ms(50);
  dWrite(LEDPIN,LOW);
  _delay_ms(500);
}

void nrBlinker(int nr)
{

  if (nr < 100)    
    for (int i=int(nr/10); i>0; i--)
      singleBlink(); // blink tens

  nr = nr - (int) (nr / 10) * 10;  
  delay(1000);

  if (nr < 10)
    for (int i=nr; i>0; i--)
      singleBlink(); // blink ones

}



// -- OneWire functions --

uint8_t owReset(int Pin)
{
  uint8_t i;

  dWrite(Pin, HIGH);
  pMode(Pin, INPUT);

  dWrite(Pin, LOW);  
  pMode(Pin, OUTPUT);    // bring low for 480us

  _delay_us(480);
  
  
  // Release line and wait for 60us
  dWrite(Pin, HIGH);
  pMode(Pin, INPUT);
  _delay_us(60);

  // store line value and wait for completion of 480us period
  i=dRead(Pin);

  _delay_us(480);
  
  // return measured line value
  return i;

}

uint8_t therm_reset()
{
  uint8_t i;

  // pull line low and wait for 480us
  THERM_LOW();
  THERM_OUTPUT_MODE();
  //therm_delay(480);
  _delay_us(480);
 
  // Release line and wait for 60us
  THERM_INPUT_MODE();
  //therm_delay(60);
  _delay_us(60);

  // store line value and wait for completion of 480us period
  i=(THERM_PIN & (1<<THERM_DQ));
  //therm_delay(420);
  _delay_us(480);
    
  // return measured line value
  return i;

}



void therm_write_bit(uint8_t bit)
{
  // pull line low for 1us
  THERM_LOW();
  THERM_OUTPUT_MODE();
  //therm_delay(1);
  _delay_us(1);
  
  // if we want to write 1, release the line (if not will keep low)
  if (bit) THERM_INPUT_MODE();  

  // wait for 60us and release the line
  //therm_delay(60);
  _delay_us(60);
  THERM_INPUT_MODE();

}

uint8_t therm_read_bit(void)
{
  uint8_t bit=0;

  // pull line low for 1us
  THERM_LOW();
  THERM_OUTPUT_MODE();
  //therm_delay(1);
  _delay_us(1);

  // release line and wait for 14us
  THERM_INPUT_MODE();
  //therm_delay(14);
  _delay_us(14);

  // read line value
  if (THERM_PIN&(1<<THERM_DQ)) bit=1;

  // wait for 45us to end and return read value
  //therm_delay(45);
  _delay_us(45);

  return bit;

}

uint8_t therm_read_byte(void)
{

  uint8_t i=8, n=0;
 
  while(i--)
  {
    // shift one position right and store read value
    n>>=1;
    n|=(therm_read_bit()<<7);
  }

  return n;
}

void therm_write_byte(uint8_t byte)
{
  uint8_t i=8;

  while(i--)
  {
    // write actual bit and shift one position right to make the next bit ready
    therm_write_bit(byte&1);
    byte>>=1;
  }

}



unsigned char therm_rom_search(unsigned char diff, unsigned char *id)
{
  // scans a one-wire bus for all attached DS18x20 sensors

  unsigned char i, j, next_diff;
  unsigned char b;

  

  if( therm_reset() )
    return PRESENCE_ERR;                       // error, no device found
    
  therm_write_byte( THERM_CMD_SEARCHROM );     // ROM search command
  next_diff = LAST_DEVICE;                     // unchanged on last device
  i = 8 * 8;                        // 8 bytes
  do
  {
    j = 8;                          // 8 bits
    do
    {
      b = therm_read_bit();      // read bit

      // read complement bit
      if( therm_read_bit() ) 
      {         
        if( b )                     // 11
          return DATA_ERR;          // data error
      } else {
        if( !b )
        {
          // 00 = 2 devices
          if( diff > i || ((*id & 1) && diff != i) )
          {
            b = 1;                  // now 1
            next_diff = i;          // next pass 0
          }
        }
      }
      therm_write_bit( b );         // write bit
      *id >>= 1;
      if( b )                       // store bit
        *id |= 0x80;
      i--;
    } while( --j );

    id++;                           // next byte
  } while( i );

  return next_diff;                 // to continue search

} 




void start_meas( void )
{
  if( PINB & 1<< THERM_DQ )
  {
    therm_write_byte(THERM_CMD_CONVERTTEMP);    // read scratchpad

    PORTB |= 1<< THERM_DQ;
    DDRB |= 1<< THERM_DQ;     // parasite power on

  } else {

    // Short circuit on bus
    _delay_ms(1000);
  }
}


int scanbus(void)
{

  // outputs the number of found devices and stores all roms in an array
  unsigned char id[8], diff;
  unsigned char i,x;
  unsigned char device_counter=0;

  // clear array

  for (x=1; x <= 20; x++)
  {
    romcodes[x][0] = 0;
  }


  for( diff = SEARCH_FIRST; diff != LAST_DEVICE; )
  {
    diff = therm_rom_search( diff, id );

    if( diff == PRESENCE_ERR )
    {
      //Serial.println("scanbus: no sensors found");
                 
      _delay_ms(1000);
      break;
    }
    if( diff == DATA_ERR )
    {
      //Serial.println("scanbus: Bus error");
      _delay_ms(1000);
      
      break;
    }

    if( id[0] == 0x28 || id[0] == 0x10 )
    {
      // valid temperature sensor found
     
      // store romcode in array
      for( i = 0; i < 8; i++ )
      {

        romcodes[device_counter][i]=id[i];       

      }

      device_counter=device_counter+1;

    }
  }

  return device_counter;
}

void therm_romtemp(uint8_t device)
{
  // address a specific sensor and retrieve its temperature

  uint8_t i;

  therm_reset();
  therm_write_byte(THERM_CMD_MATCHROM);
  for (i=0 ; i < 8; i++)
  {
    therm_write_byte(romcodes[device][i]);
  }
  therm_write_byte(THERM_CMD_CONVERTTEMP);

  // wait until conversion is complete
  while(!therm_read_bit());



  therm_reset();
  therm_write_byte(THERM_CMD_MATCHROM);
  for (i=0 ; i < 8; i++)
  {
    therm_write_byte(romcodes[device][i]);
  }
  therm_write_byte(THERM_CMD_RSCRATCHPAD);

  // store the replies in the 'scratchpad' variable
  for (i=0 ; i < 2; i++)
  {
    scratchpad[i]=therm_read_byte();
  }
  therm_reset();

}


void showdevs()
{
  // outputs all device romcodes stored in the array

  unsigned char device=0;
  unsigned char rombyte=0;
  uint8_t digit;
  uint16_t decimal;
 
  while (1)
  {

    if (romcodes[device][0] != 0)
    {

      // valid romcode found in array 

      // target the sensor and read its temperature
      therm_romtemp(device);   // this fills the 'scratchpad' variable



      for (rombyte=0; rombyte < 8; rombyte++)
      {        
         
        //Serial.print(romcodes[device][rombyte],HEX); // display the romcode 
        //Serial.print(" ");
      } 

      //Serial.print("  ");

      // store temperature integer digits and decimal digits


      // display the 'scratchpad' variable fields

      // --half degree accuracy --   (9 bit)
      // test if temperature is .0 or .5
      //decimal = scratchpad[0] & (1 << 0);  // decimals is in bit 0, store value
      // move temperature bits on position to the right
      //scratchpad[0]>>=1;
      //Serial.print(scratchpad[0]);
      //if (decimal == 0)
      //  Serial.print(".0");
      //else 
      //  Serial.print(".5");



      // -- 2-decimal of a degree accuracy -- (12 bit)
      // store whole digits
      digit=scratchpad[0]>>4;
      digit|=(scratchpad[1]&0x7)<<4;
      // store decimal digits
      decimal=scratchpad[0]&0xf;
      decimal*=THERM_DECIMAL_STEPS_12BIT;

      //Serial.print(digit);
      //Serial.print(".");
      //Serial.print(decimal);
      //Serial.print(" C");
      
      nrBlinker(digit); 
      _delay_ms(1000);

      // decimals are stored as a 4-digit positive number (e.g. 3625), scale back to < 100
      decimal = (int) (decimal / 100);
      nrBlinker(decimal); 
         
      _delay_ms(1000);
      _delay_ms(1000);

      device=device+1;

    } else {

      break;

    }

  } 

}




void loop()
{ 
  

  uint8_t  ack;
  int devs;  
 
  while (1)
  {

    ack = owReset(THERM_DQ);

    if (ack == 1)
    {

      // no sensors found
      nrBlinker(2);

    } else {

      // sensor activity detected       

      devs=scanbus();  // detect and store device rom's in an array       
        
      if (devs > 0)
      {
    
        _delay_ms(1000);
        _delay_ms(1000);

        showdevs();

      } else {

        // unable to get sensible data back from sensors
 
      }


      _delay_ms(1000);
      _delay_ms(1000);
      _delay_ms(1000);
      _delay_ms(1000);


    }

    _delay_ms(1000);
    _delay_ms(1000);
  
  } 
}