ATtiny85 DS18B20: Difference between revisions
Jump to navigation
Jump to search
(Created page with " <pre> /* DS18B20 code for ATMega328 (arduino) 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...") |
No edit summary |
||
(One intermediate revision by the same user not shown) | |||
Line 2: | Line 2: | ||
<pre> |
<pre> |
||
/* |
/* |
||
DS18B20 code for ATMega328 (arduino) |
|||
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. |
This code does not rely on any external OneWire or DallasTemperature sensor libraries. |
||
Line 13: | Line 26: | ||
------------------------- |
------------------------- |
||
⚫ | |||
DS18S20 |
DS18S20 |
||
Line 47: | Line 57: | ||
*/ |
|||
#include <avr/io.h> |
|||
#include <util/delay.h> |
|||
//#include <string.h> |
|||
//#include <math.h> |
|||
#define THERM_PORT PORTB |
#define THERM_PORT PORTB |
||
#define THERM_DDR DDRB |
#define THERM_DDR DDRB |
||
#define THERM_PIN PINB |
#define THERM_PIN PINB |
||
#define THERM_DQ |
#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 104: | Line 112: | ||
{ |
{ |
||
Serial.begin(9600); |
|||
} |
} |
||
Line 139: | Line 147: | ||
} |
} |
||
} |
} |
||
void singleBlink() |
|||
{ |
|||
pMode(LEDPIN,OUTPUT); |
|||
dWrite(LEDPIN,HIGH); |
|||
⚫ | |||
dWrite(LEDPIN,LOW); |
|||
⚫ | |||
} |
|||
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 462: | Line 496: | ||
{ |
{ |
||
Serial.print(romcodes[device][rombyte],HEX); // display the romcode |
//Serial.print(romcodes[device][rombyte],HEX); // display the romcode |
||
Serial.print(" "); |
//Serial.print(" "); |
||
} |
} |
||
Serial.print(" "); |
//Serial.print(" "); |
||
// store temperature integer digits and decimal digits |
// store temperature integer digits and decimal digits |
||
Line 494: | Line 528: | ||
decimal*=THERM_DECIMAL_STEPS_12BIT; |
decimal*=THERM_DECIMAL_STEPS_12BIT; |
||
Serial.print(digit); |
//Serial.print(digit); |
||
Serial.print("."); |
//Serial.print("."); |
||
Serial.print(decimal); |
//Serial.print(decimal); |
||
Serial.print(" C"); |
//Serial.print(" C"); |
||
nrBlinker(digit); |
|||
⚫ | |||
// 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); |
||
Line 516: | Line 554: | ||
} |
} |
||
Line 522: | Line 561: | ||
{ |
{ |
||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
while (1) |
while (1) |
||
{ |
{ |
||
ack = owReset(THERM_DQ); |
ack = owReset(THERM_DQ); |
||
Line 536: | Line 573: | ||
{ |
{ |
||
// |
// no sensors found |
||
nrBlinker(2); |
|||
} else { |
} else { |
||
// sensor activity detected |
// sensor activity detected |
||
while (1) |
|||
{ |
|||
devs=scanbus(); // detect and store device rom's in an array |
|||
if (devs > 0) |
|||
{ |
|||
_delay_ms(1000); |
|||
_delay_ms(1000); |
|||
showdevs(); |
|||
showdevs(); |
|||
} else { |
|||
Serial.println(" sensors found"); |
|||
} |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
// 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); } }