// Simple 1-Wire Interface
// From: http://www.technoblogy.com/show?1LJD
// By : David Johnson-Davies
//
// Code:
// http://www.technoblogy.com/list?1MLP
//
// Wokwi does not have the Sparkfun 7-segment
// display, so that is not used.
// The TinyDebug is used instead to display
// the temperature.
//
// The timing with the Timer1 does not seem to work in Wokwi.
// That has been changed as well.
/* 1-Wire Interface v2
David Johnson-Davies - www.technoblogy.com - 19th August 2018
ATtiny85 @ 8 MHz (internal oscillator; BOD disabled)
CC BY 4.0
Licensed under a Creative Commons Attribution 4.0 International license:
http://creativecommons.org/licenses/by/4.0/
*/
#include <TinyDebug.h> // Added for Wokwi
// One Wire Protocol **********************************************
// Buffer to read data or ROM code
static union {
uint8_t DataBytes[9];
unsigned int DataWords[4];
};
const int OneWirePin = 3;
const int ReadROM = 0x33;
const int MatchROM = 0x55;
const int SkipROM = 0xCC;
const int ConvertT = 0x44;
const int ReadScratchpad = 0xBE;
inline void PinLow () {
DDRB = DDRB | 1<<OneWirePin;
}
inline void PinRelease () {
DDRB = DDRB & ~(1<<OneWirePin);
}
// Returns 0 or 1
inline uint8_t PinRead () {
return PINB>>OneWirePin & 1;
}
void DelayMicros (int micro) {
TCNT1 = 0;
TIFR = 1<<OCF1A;
OCR1A = (micro>>1) - 1;
while ((TIFR & 1<<OCF1A) == 0);
}
void LowRelease (int low, int high) {
PinLow();
delayMicroseconds(low); //DelayMicros(low);
PinRelease();
delayMicroseconds(high); //DelayMicros(high);
}
uint8_t OneWireSetup () {
TCCR1 = 0<<CTC1 | 0<<PWM1A | 5<<CS10; // CTC mode, 500kHz clock
GTCCR = 0<<PWM1B;
}
uint8_t OneWireReset () {
uint8_t data = 1;
LowRelease(480, 70);
data = PinRead();
delayMicroseconds(410); //DelayMicros(410);
return data; // 0 = device present
}
void OneWireWrite (uint8_t data) {
int del;
for (int i = 0; i<8; i++) {
if ((data & 1) == 1) del = 6; else del = 60;
LowRelease(del, 70 - del);
data = data >> 1;
}
}
uint8_t OneWireRead () {
uint8_t data = 0;
for (int i = 0; i<8; i++) {
LowRelease(6, 9);
data = data | PinRead()<<i;
delayMicroseconds(55); // DelayMicros(55);
}
return data;
}
// Read bytes into array, least significant byte first
void OneWireReadBytes (int bytes) {
for (int i=0; i<bytes; i++) {
DataBytes[i] = OneWireRead();
}
}
// Calculate CRC over buffer - 0x00 is correct
uint8_t OneWireCRC (int bytes) {
uint8_t crc = 0;
for (int j=0; j<bytes; j++) {
crc = crc ^ DataBytes[j];
for (int i=0; i<8; i++) crc = crc>>1 ^ ((crc & 1) ? 0x8c : 0);
}
return crc;
}
// Serial Seven-Segment Display **********************************************
const int Select = 0;
const int DataOut = 1;
const int ClockPin = 2;
const int Clear_Display = 0x76;
const int Cursor_Control = 0x79;
const int Decimal_Control = 0x77;
void SendByte(char data) {
digitalWrite(Select, LOW);
shiftOut(DataOut, ClockPin, MSBFIRST, data);
digitalWrite(Select, HIGH);
}
// Clear display
void ClearDisplay () {
SendByte(Clear_Display);
}
// Display Error
void DisplayError (char *str) {
SendByte(Clear_Display);
SendByte(Cursor_Control);
SendByte(0);
while (*str) SendByte(*str++);
}
// Display a four digit hexadecimal number
void Display (int n) {
SendByte(Cursor_Control);
SendByte(0);
for (int i=12; i>=0; i=i-4) {
SendByte((n>>i) & 0x0F);
}
}
// Display temperature
void DisplayTemp (int t) {
SendByte(Cursor_Control);
SendByte(0);
int temp = t>>4;
int points = 0x20; // Display degree symbol
if (temp>=100) SendByte(temp/100); // Hundreds
if (temp<0) SendByte('-');
SendByte((abs(temp)/10) % 10); // Tens
SendByte(abs(temp) % 10); // Units
if (temp>=0 && temp<100) {
points = 0x22; // Display decimal point
SendByte(((t & 0x0F)*10)>>4); // Tenths
}
SendByte(Decimal_Control);
SendByte(points);
SendByte('C');
}
// Setup **********************************************
void setup() {
Debug.begin(); // Added for Wokwi
Debug.println(F("Hello, TinyDebug!")); // Added for Wokwi
pinMode(ClockPin, OUTPUT);
pinMode(DataOut, OUTPUT);
pinMode(Select, OUTPUT);
digitalWrite(Select, HIGH);
digitalWrite(ClockPin, LOW);
digitalWrite(DataOut, LOW);
OneWireSetup();
}
// Read temperature of a single DS18B20 or MAX31820 on the bus
void Temperature () {
cli(); // No interrupts
if (OneWireReset() != 0) {
sei();
DisplayError("Err");
Debug.println(F("Err1"));
} else {
OneWireWrite(SkipROM);
OneWireWrite(ConvertT);
while (OneWireRead() != 0xFF);
OneWireReset();
OneWireWrite(SkipROM);
OneWireWrite(ReadScratchpad);
OneWireReadBytes(9);
sei(); // Interrupts
if (OneWireCRC(9) == 0) {
DisplayTemp(DataWords[0]);
Debug.println(DataWords[0]);
} else
{
DisplayError("Crc");
Debug.println(F("Crc2"));
}
}
delay(1000);
}
// Display serial number of a single device on the 1-wire bus
void SerialNumber () {
ClearDisplay();
cli();
if (OneWireReset() != 0) {
sei();
DisplayError("Err");
Debug.println(F("Err3"));
} else {
OneWireWrite(ReadROM);
OneWireReadBytes(8);
sei();
if (OneWireCRC(8) == 0) {
for (int i=3; i>=0; i--) {
Display(DataWords[i]);
Debug.println(DataWords[i]);
delay(1000);
}
} else
{
DisplayError("Crc");
Debug.println(F("Crc4"));
}
}
delay(1000);
}
void loop () {
Temperature();
SerialNumber();
}