/*
control thermosensor DS18B20
This sketch uses the Serial.read() function in order to query a thermo sensor
Circuit:
- digital pin 2
- GND
Command set:
:MEAS:TEMP? <D> (acquire measurements for all sensors, read single sensor)
:SYS:ERR? -> <error number>, <error message>
*STB -> <status byte>
*IDN? -> <Manufacturer>,<Model>,<ID>,<FW>
:CONF? ->
:INFO? -> <Serial Number>,<Part Number>,<Card Firmware Rev>,<HW Rev>,<Assembly Date>,<Description>
:DEV:INFO? <D> -> <sensor serial number>,<sensor model number>
created 24 July 2022
by Gregor Popp
modified 24 July 2022
by Gregor Popp
*/
#include <ctype.h>
#include <OneWire.h>
#include <DallasTemperature.h>
// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2 // #replace with const
#define TEMPERATURE_PRECISION 12 // #replace with const
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
// arrays to hold device addresses
DeviceAddress Thermometer[12];
float tempC;
byte nsensors;
byte x;
// parameters of sensor connection
const String IDN = "Dallas Semiconductor,DS18B20-PAR+T&R,n/a,1.0"; // #ID auslesen
// Manufacturer,Model,ID,FW
const String CONFIG = "1-wire PIN = 2";
const String INFO = ",DS18B20-PAR+T&R,1.00,n/a,20220726,n/a";
// <Serial Number>,<Part Number>,<Card Firmware Rev>,<OSW Module Firmware Rev>,
// <OPM Module firmware Rev>,<HW Rev>,<Assembly Date>,<Description>
// 29374743,OSC-A1 1234 ,2.00,3.00,3.00,3.00, 20010815, Custom for IE MRR
char *DEVINFO[] = {"2022-18-15936,SW1x4"}; // #auslesen
// <serial number>,<model number>
const int errN[] = {0, -102, -224, -227, -222, -500};
char *errText[] = {"\"no error\"", "\"Syntax error\"", "\"Illegal parameter value\"",
"\"Invalid device address\"", "\"Data out of range\"",
"\"Unable to find address for 1-wire device\""
};
const byte numChars = 32;
int errornumber = 0;
struct parsedDataS {
char command[numChars] = {0};
int device = 0;
};
struct recvDataS {
char receivedChars[numChars] = {0};
boolean newData = false;
};
const float minimumValue = -60.;
const float maximumValue = 120.;
//============
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Serial.println("WOKWI"); // only for input line in wokwi
// Start up the library
sensors.begin();
nsensors = sensors.getDeviceCount();
nsensors = 1; // #debug
oneWire.reset_search();
for (x = 0; x < nsensors; x ++)
{
if (!oneWire.search(Thermometer[x])) {
Serial.println("Unable to find address for insideThermometer");
// errornumber = 5;
}
else {
Serial.print("Device ");
Serial.print(x, DEC);
Serial.print(" Address: ");
printAddress(Thermometer[x]);
Serial.print(" Resolution: ");
Serial.print(sensors.getResolution(Thermometer[x]), DEC);
Serial.println();
}
}
}
//============
void loop() {
char receivedChars[numChars];
recvDataS rB;
parsedDataS rP;
char tempChars[numChars]; // temporary array for use when parsing
rB = recvWithStartEndMarkers();
if (rB.newData == true) {
strcpy(tempChars, rB.receivedChars);
// this temporary copy is necessary to protect the original data
// because strtok() used in parseData() replaces the commas with \0
rP = parseData(tempChars);
selectCommand(rP);
}
else {
delay(200);
}
}
recvDataS recvWithStartEndMarkers() {
boolean newDataRecv = false; // newDataRecv = newData
char receivedChars[numChars];
recvDataS rbuf;
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarkerCCQH = '*';
//Common Command and Query Headers
char startMarkerIQH = ':';
// Instrument-Control Headers
char endMarker = '\n';
char rc;
while (Serial.available() > 0 && newDataRecv == false) {
rc = Serial.read();
rc = toupper(rc);
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newDataRecv = true;
}
}
else if (rc == startMarkerCCQH || rc == startMarkerIQH) {
recvInProgress = true;
}
}
strcpy(rbuf.receivedChars, receivedChars);
rbuf.newData = newDataRecv;
return rbuf;
}
//============
parsedDataS parseData(char tempChars[numChars]) { // split the data into its parts
parsedDataS pbuf;
char * strtokIndx; // this is used by strtok() as an index
strtokIndx = strtok(tempChars, " "); // get the first part - the string
strcpy(pbuf.command, strtokIndx); // copy it to command
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
pbuf.device = atoi(strtokIndx); // convert this part to an integer
return pbuf;
}
//============
void selectCommand(parsedDataS pBuf) {
if (strcmp(pBuf.command, "IDN?") == 0) {
// *idn?
Serial.println(IDN);
}
else if (strcmp(pBuf.command, "MEAS:TEMP?") == 0) {
// :MEASure:TEMPerature? <D>
// :MEAS:TEMP? <D>,<Input>,<Output>
measTemp(pBuf);
}
else if (strcmp(pBuf.command, "CONF?") == 0) {
// :CONF?
// :CONFig?
Serial.println(CONFIG);
}
else if (strcmp(pBuf.command, "INFO?") == 0) {
// :INFOrmation?
// :INFO?
Serial.println(INFO);
}
else if (strcmp(pBuf.command, "DEV:INFO?") == 0) {
// :DEVice:INFOrmation? <D>
if ( inRange(pBuf.device, 1, nsensors) ) {
// check <D> in range
Serial.println(DEVINFO[pBuf.device - 1]);
}
else {
errornumber = 2;
}
}
else if (strcmp(pBuf.command, "SYST:ERR?") == 0) {
querySysErr();
}
else if (strcmp(pBuf.command, "STB?") == 0) {
// *STB?
Serial.println("*STB?");
Serial.println((errornumber > 0) << 5);
}
else {
errornumber = 1;
}
}
//============
bool inRange(int val, int minimum, int maximum)
{
return ((minimum <= val) && (val <= maximum));
}
//============
void measTemp(parsedDataS pBuf) {
// Serial.println(pBuf.device); // debug, bei pBuf.device == 0 alle Sensoren auslesen?
if ( inRange(pBuf.device, 1, nsensors) ) {
// sensors.requestTemperatures(); // alle Sensoren messen
sensors.requestTemperaturesByAddress(Thermometer[pBuf.device]);
// bool abfragen, ob Adresse bekannt, Fehler 3
tempC = sensors.getTempC(Thermometer[pBuf.device]);
tempC = 22.222; // #debug
// Plausibilitätsprüfung
if ( inRange(tempC, minimumValue, maximumValue) ) {
Serial.println(tempC);
}
else {
errornumber = 4; // Data out of range
}
}
else {
errornumber = 3; // Invalid device address
}
}
//============
void querySysErr() {
errornumber = abs(errornumber); // Vorbeugung
Serial.print(errN[errornumber]);
Serial.print(", ");
Serial.println(errText[errornumber]);
errornumber = 0;
}
//============
// function to print a device address
void printAddress(DeviceAddress deviceAddress)
{
for (uint8_t i = 0; i < 8; i++)
{
// zero pad the address if necessary
if (deviceAddress[i] < 16) Serial.print("0");
Serial.print(deviceAddress[i], HEX);
}
}
//============