Created
October 6, 2018 09:55
-
-
Save Links2004/743ee62f2fcb682426f0276b8526d9e6 to your computer and use it in GitHub Desktop.
Arduino async multi onewire 1wire bus
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* | |
* Created on: Jul 21, 2018 | |
* Author: links | |
*/ | |
#include <OneWire.h> | |
#include "dev_ids.h" | |
#ifdef ARDUINO_AVR_MEGA2560 | |
#define BUSCOUNT (32) | |
#else | |
#define BUSCOUNT (11) | |
#endif | |
#define SHOW_RAW | |
//#define SHOW_SCAN | |
#ifdef ARDUINO_AVR_MEGA2560 | |
#if BUSCOUNT == 32 | |
OneWire * oneWireBus[BUSCOUNT] = { new OneWire(22), new OneWire(23), new OneWire(24), new OneWire(25), new OneWire(26), new OneWire(27), new OneWire(28), new OneWire(29), new OneWire(30), new OneWire(31), new OneWire(32), new OneWire(33), new OneWire(34), new OneWire(35), new OneWire(36), new OneWire(37), new OneWire(38), new OneWire(39), new OneWire(40), new OneWire(41), new OneWire(42), new OneWire(43), new OneWire(44), new OneWire(45), new OneWire(46), new OneWire(47), new OneWire(48), new OneWire(49), new OneWire(50), new OneWire(51), new OneWire(52), new OneWire(53) }; | |
#else | |
#error BUS COUNT not matched | |
#endif | |
#else | |
#if BUSCOUNT == 6 | |
OneWire * oneWireBus[BUSCOUNT] = { new OneWire(9), new OneWire(8), new OneWire(7), new OneWire(6), new OneWire(5), new OneWire(4) }; | |
#elif BUSCOUNT == 11 | |
OneWire * oneWireBus[BUSCOUNT] = { new OneWire(9), new OneWire(8), new OneWire(7), new OneWire(6), new OneWire(5), new OneWire(4), new OneWire(A2), new OneWire(A3), new OneWire(A4), new OneWire(A5), new OneWire(A1) }; | |
#else | |
#error BUS COUNT not matched | |
#endif | |
#endif | |
char format[40] = { 0 }; | |
void setup() { | |
Serial.begin(115200); | |
Serial.setTimeout(1000); | |
Serial.println("BOOT"); | |
} | |
#define PRINT_BUS Serial.print("BUS:"); Serial.print(id); Serial.print('\t'); | |
//Serial.print(" round:"); Serial.print(round); | |
bool busloop(uint8_t id, uint8_t round) { | |
OneWire * oneWire = oneWireBus[id]; | |
uint8_t device_rom[8]; | |
#ifdef SHOW_SCAN | |
PRINT_BUS | |
Serial.println("START"); | |
#endif | |
//oneWire->depower(); | |
oneWire->reset(); | |
while(1) { | |
delay(20); | |
if(!oneWire->search(device_rom)) { | |
#ifdef SHOW_SCAN | |
PRINT_BUS | |
Serial.println("FIN"); | |
#endif | |
oneWire->reset_search(); | |
//oneWire->power(); | |
return false; | |
} | |
w1IdType_t device_type = (w1IdType_t) device_rom[0]; | |
snprintf(format, sizeof(format), "BUS:%d\tROM:%02x-%02x%02x%02x%02x%02x%02x\t", id, device_type, device_rom[6], device_rom[5], device_rom[4], device_rom[3], device_rom[2], device_rom[1]); | |
Serial.print(format); | |
if(device_rom[7] != oneWire->crc8(device_rom, 7)) { | |
Serial.println("ERROR:CRC not valid!"); | |
return false; | |
} | |
bool device_is_present = oneWire->reset(); | |
if(!device_is_present) { | |
Serial.println("ERROR:Device missing"); | |
continue; | |
} | |
switch(device_type) { | |
case DS18S20: | |
case DS18B20: | |
case DS1822: | |
oneWire->select(device_rom); | |
if(round == 0) { | |
oneWire->write(0x44, 1); // start conversion, with parasite power on at the end | |
Serial.println("INFO:start conversion"); | |
//delay(50); | |
} else { | |
/* | |
oneWire->write(0x44, 1); // start conversion, with parasite power on at the end | |
unsigned long now = millis(); | |
while(oneWire->read_bit() != 1) { | |
delay(10); | |
} | |
Serial.print(" ms "); | |
Serial.print(millis() - now); | |
//delay(750); // maybe 750ms is enough, maybe not | |
// we might do a oneWire->depower() here, but the reset will take care of it. | |
device_is_present = oneWire->reset(); | |
if(!device_is_present) { | |
continue; | |
} | |
oneWire->select(device_rom); | |
*/ | |
oneWire->write(0xBE); // Read Scratchpad | |
uint8_t device_data[12]; | |
oneWire->read(device_data, 9); | |
#ifdef SHOW_RAW | |
Serial.print("DATA:"); | |
// we need 9 bytes | |
for(uint8_t index = 0; index < 9; index++) { | |
snprintf(format, sizeof(format), "%02X", device_data[index]); | |
Serial.print(format); | |
} | |
Serial.print('\t'); | |
#endif | |
if(device_data[8] != oneWire->crc8(device_data, 8)) { | |
Serial.println("ERROR:CRC not valid!"); | |
return false; | |
} | |
//Serial.println(); | |
// Convert the device_data to actual temperature | |
// because the result is a 16 bit signed integer, it should | |
// be stored to an "int16_t" type, which is always 16 bits | |
// even when compiled on a 32 bit processor. | |
int16_t raw = (device_data[1] << 8) | device_data[0]; | |
if(raw == 0x550) { | |
Serial.println("ERROR:default Value"); | |
continue; | |
} | |
if(device_type == DS18S20) { | |
raw = raw << 3; // 9 bit resolution default | |
if(device_data[7] == 0x10) { | |
// "count remain" gives full 12 bit resolution | |
raw = (raw & 0xFFF0) + 12 - device_data[6]; | |
} | |
} else { | |
const uint8_t cfg = (device_data[4] & 0x60); | |
// at lower res, the low bits are undefined, so let's zero them | |
if(cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms | |
else if(cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms | |
else if(cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms | |
//// default is 12 bit resolution, 750 ms conversion time | |
} | |
const float celsius = (float) raw / 16.0f; | |
Serial.print("TEMP:"); | |
Serial.println(celsius, 3); | |
} | |
break; | |
case DS2406: | |
oneWire->select(device_rom); | |
uint8_t device_data[12]; | |
uint16_t crcr; | |
device_data[0] = DS2406_ACCESS_READ; | |
device_data[1] = 0x4D; | |
device_data[2] = 0xFF; | |
oneWire->write(device_data, 3); | |
oneWire->read(&device_data[3], 2); | |
crcr = oneWire->read(); | |
crcr |= ((unsigned int) (oneWire->read())) << 8; | |
#ifdef SHOW_RAW | |
Serial.print("DATA:"); | |
for(uint8_t index = 3; index < 5; index++) { | |
snprintf(format, sizeof(format), "%02X", device_data[index]); | |
Serial.print(format); | |
} | |
Serial.print('\t'); | |
#endif | |
if(crcr == 0xFFFF) { | |
Serial.println("ERROR:No Answer"); | |
return false; | |
} | |
if(crcr != ~oneWire->crc16(device_data, 5)) { | |
Serial.println("ERROR:CRC not valid!"); | |
return false; | |
} | |
oneWire->reset(); | |
Serial.print("STATE:"); | |
Serial.println(~(device_data[4]) & 0b11); | |
break; | |
default: | |
Serial.println("ERROR:Device not implemented"); | |
break; | |
} | |
} | |
} | |
uint8_t readHEX(const char * str) { | |
const char in[3] = { str[0], str[1], 0x00 }; | |
return strtoul(in, NULL, 16); | |
} | |
void loop() { | |
static uint8_t x = 0; | |
for(uint8_t i = 0; i < BUSCOUNT; i++) { | |
busloop(i, x); | |
} | |
x++; | |
if(x >= 2) { | |
x = 0; | |
} | |
if(Serial.available() > 0) { | |
String line = Serial.readStringUntil('\n'); | |
// WRITE 04 12-00000023ec76 03 | |
// WRITE 04 12-00000023ec76 02 | |
// WRITE 04 12-00000023ec76 00 | |
if(line.startsWith("WRITE ") && line.length() > (25)) { | |
line.remove(0, 6); | |
uint8_t device_rom[8] = { 0 }; | |
const char * buf = line.c_str(); | |
uint8_t id = readHEX(buf); | |
buf += 3; | |
if(id > (uint8_t) BUSCOUNT) { | |
Serial.println("WRITE\tERROR:BUS id wrong"); | |
return; | |
} | |
OneWire * oneWire = oneWireBus[id]; | |
device_rom[0] = readHEX(buf); | |
buf += 3; | |
device_rom[6] = readHEX(buf); | |
buf += 2; | |
device_rom[5] = readHEX(buf); | |
buf += 2; | |
device_rom[4] = readHEX(buf); | |
buf += 2; | |
device_rom[3] = readHEX(buf); | |
buf += 2; | |
device_rom[2] = readHEX(buf); | |
buf += 2; | |
device_rom[1] = readHEX(buf); | |
buf += 2; | |
// add CRC | |
device_rom[7] = oneWire->crc8(device_rom, 7); | |
w1IdType_t device_type = (w1IdType_t) device_rom[0]; | |
snprintf(format, sizeof(format), "BUS:%d\tROM:%02x-%02x%02x%02x%02x%02x%02x\tWRITE\t", id, device_rom[0], device_rom[6], device_rom[5], device_rom[4], device_rom[3], device_rom[2], device_rom[1]); | |
Serial.print(format); | |
line.remove(0, 19); | |
buf = line.c_str(); | |
switch(device_type) { | |
case DS2406: | |
if(line.length() >= 2) { | |
uint8_t data = readHEX(buf); | |
Serial.print("DATA:"); | |
Serial.print(data, HEX); | |
Serial.print('\t'); | |
uint8_t state = ((data & 0b11) << 5) | 0xf; | |
bool device_is_present = oneWire->reset(); | |
if(!device_is_present) { | |
Serial.println("ERROR:Device missing"); | |
return; | |
} | |
oneWire->select(device_rom); | |
uint8_t out[4]; | |
uint16_t crcr; | |
out[0] = DS2406_WRITE_STATUS; | |
out[1] = 0x07; | |
out[2] = 0x00; | |
out[3] = state; | |
oneWire->write(out, 4); | |
crcr = oneWire->read(); | |
crcr |= ((unsigned int) (oneWire->read())) << 8; | |
if(crcr == 0xFFFF) { | |
Serial.println("ERROR:No Answer"); | |
return; | |
} | |
if(crcr != ~oneWire->crc16(out, 4)) { | |
Serial.println("ERROR:CRC not valid!"); | |
return; | |
} | |
// Write the status back. | |
oneWire->write(0xFF, 1); | |
oneWire->read(); | |
Serial.println("OK"); | |
} else { | |
Serial.println("ERROR:To less data"); | |
} | |
break; | |
default: | |
Serial.println("ERROR:Device not implemented"); | |
break; | |
} | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment