ATtiny85 DS18B20: Difference between revisions
Jump to navigation
Jump to search
No edit summary |
(No difference)
|
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); } }