Hello,
I have the problem, that the Arduino system is executing my code but it is hanging at the point "BA - Patientenmonitor".
If I execute the code without the Ds18b20, then it works without a problem, but with the Ds18b20 integrated, it don't works.
Please can anyone give me some advise?
Here are the code and some pictures:
With Ds18b20 Sensor:
#include <Wire.h>
#include <avr/pgmspace.h>
#include <EEPROM.h>
#include <avr/sleep.h>
#include "ssd1306h.h"
#include "MAX30102.h"
#include "Pulse.h"
#include <OneWire.h>
#include <DallasTemperature.h>
#define LED LED_BUILTIN
#define BUTTON 3
#define OPTIONS 7
#define ONE_WIRE_BUS 2 // Datenpin des DS18B20 an Pin 2 des Arduino anschließen
SSD1306 oled_screen;
MAX30102 max_sensor;
Pulse pulseIR;
Pulse pulseRed;
MAFilter bpm;
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
static const uint8_t heart_bits[] PROGMEM = { 0x00, 0x00, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0xfe, 0xff,
0xfe, 0xff, 0xfc, 0x7f, 0xf8, 0x3f, 0xf0, 0x1f, 0xe0, 0x0f,
0xc0, 0x07, 0x80, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00 };
const uint8_t spo2_table[184] PROGMEM =
{ 95, 95, 95, 96, 96, 96, 97, 97, 97, 97, 97, 98, 98, 98, 98, 98, 99, 99, 99, 99,
99, 99, 99, 99, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 99, 99, 99, 99, 99, 99, 99, 99, 98, 98, 98, 98, 98, 98, 97, 97,
97, 97, 96, 96, 96, 96, 95, 95, 95, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91, 91,
90, 90, 89, 89, 89, 88, 88, 87, 87, 86, 86, 85, 85, 84, 84, 83, 82, 82, 81, 81,
80, 80, 79, 78, 78, 77, 76, 76, 75, 74, 74, 73, 72, 72, 71, 70, 69, 69, 68, 67,
66, 66, 65, 64, 63, 62, 62, 61, 60, 59, 58, 57, 56, 56, 55, 54, 53, 52, 51, 50,
49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 31, 30, 29,
28, 27, 26, 25, 23, 22, 21, 20, 19, 17, 16, 15, 14, 12, 11, 10, 9, 7, 6, 5,
3, 2, 1 } ;
int getVCC() {
#if defined(__AVR_ATmega1284P__)
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); // For ATmega1284
#else
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); // For ATmega328
#endif
delay(2); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA, ADSC));
uint8_t low = ADCL;
unsigned int val = (ADCH << 8) | low;
//discard previous result
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA, ADSC));
low = ADCL;
val = (ADCH << 8) | low;
return (((long)1024 * 1100) / val)/100;
}
void print_digit(int x, int y, long val, char c=' ', uint8_t field = 3,const int BIG = 1)
{
uint8_t ff = field;
do {
char ch = (val!=0) ? val%10+'0': c;
oled_screen.drawChar( x+BIG*(ff-1)*6, y, ch, BIG);
val = val/10;
--ff;
} while (ff>0);
}
const uint8_t MAXWAVE = 72;
class Waveform {
public:
Waveform(void) {wavep = 0;}
void record(int waveval) {
waveval = waveval/8;
waveval += 128;
waveval = waveval<0? 0 : waveval;
waveform[wavep] = (uint8_t) (waveval>255)?255:waveval;
wavep = (wavep+1) % MAXWAVE;
}
void scale() {
uint8_t maxw = 0;
uint8_t minw = 255;
for (int i=0; i<MAXWAVE; i++) {
maxw = waveform[i]>maxw?waveform[i]:maxw;
minw = waveform[i]<minw?waveform[i]:minw;
}
uint8_t scale8 = (maxw-minw)/4 + 1;
uint8_t index = wavep;
for (int i=0; i<MAXWAVE; i++) {
disp_wave[i] = 31-((uint16_t)(waveform[index]-minw)*8)/scale8;
index = (index + 1) % MAXWAVE;
}
}
void draw(uint8_t X) {
for (int i=0; i<MAXWAVE; i++) {
uint8_t y = disp_wave[i];
oled_screen.drawPixel(X+i, y);
if (i<MAXWAVE-1) {
uint8_t nexty = disp_wave[i+1];
if (nexty>y) {
for (uint8_t iy = y+1; iy<nexty; ++iy)
oled_screen.drawPixel(X+i, iy);
}
else if (nexty<y) {
for (uint8_t iy = nexty+1; iy<y; ++iy)
oled_screen.drawPixel(X+i, iy);
}
}
}
}
private:
uint8_t waveform[MAXWAVE];
uint8_t disp_wave[MAXWAVE];
uint8_t wavep = 0;
} wave;
int beatAvg;
int SPO2, SPO2f;
int voltage;
bool filter_for_graph = false;
bool draw_Red = false;
uint8_t pcflag =0;
uint8_t istate = 0;
uint8_t sleep_counter = 0;
float tempC;
void button(void){
pcflag = 1;
}
void checkbutton(){
if (pcflag && !digitalRead(BUTTON)) {
istate = (istate +1) % 4;
filter_for_graph = istate & 0x01;
draw_Red = istate & 0x02;
EEPROM.write(OPTIONS, filter_for_graph);
EEPROM.write(OPTIONS+1, draw_Red);
}
pcflag = 0;
}
void Display_5(){
if(pcflag && !digitalRead(BUTTON)){
draw_oled_screen(5);
delay(1100);
}
pcflag = 0;
}
void go_sleep() {
oled_screen.fill(0);
oled_screen.off();
delay(10);
max_sensor.off();
delay(10);
cbi(ADCSRA, ADEN);
delay(10);
pinMode(0,INPUT);
pinMode(2,INPUT);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_mode();
// cause reset
setup();
}
void draw_oled_screen(int msg) {
oled_screen.firstPage();
do{
switch(msg){
case 0: oled_screen.drawStr(10,0,F("Device error"),1);
break;
case 1: oled_screen.drawStr(35,7,F("PLACE YOUR"),1);
oled_screen.drawStr(45,17,F("FINGER"),1);
break;
case 2: oled_screen.drawStr(0,0,F("Pulse Rate"),1);
print_digit(70,0,beatAvg);
oled_screen.drawStr(95,0,F("BPM"),1);
oled_screen.drawStr(15,9,F("Oxygen"),1);
oled_screen.drawStr(0,16,F("Saturation"),1);
print_digit(70,13,SPO2f,' ',3,1);
oled_screen.drawChar(95,13,'%',1);
oled_screen.drawStr(0,25,F("Temperature"),1);
print_digit(70,25,tempC);
oled_screen.drawStr(95,25,F("C"),1);
break;
case 3: oled_screen.drawStr(0,8,F("BA - Patientenmonitor"),1);
oled_screen.drawStr(55,20,F("GE"),1);
//oled.drawXBMP(6,8,16,16,heart_bits);
break;
case 4: oled_screen.drawStr(28,12,F("OFF IN"),1);
oled_screen.drawChar(76,12,10-sleep_counter/10+'0');
oled_screen.drawChar(82,12,'s');
break;
case 5: oled_screen.drawStr(0,0,F("AVG Pulse"),1);
print_digit(70,0,beatAvg);
oled_screen.drawStr(95,0,F("BPM"),1);
oled_screen.drawStr(0,9,F("AVG Oxygen"),1);
oled_screen.drawStr(0,16,F("Saturation"),1);
print_digit(70,13,SPO2);
oled_screen.drawChar(95,13,'%',1);
break;
}
} while (oled_screen.nextPage());
}
void setup(void) {
Serial.begin(9600); // Start serial communication at 9600 baud
Serial.println("Starting setup");
sensors.begin();
pinMode(LED, OUTPUT);
pinMode(BUTTON, INPUT_PULLUP);
filter_for_graph = EEPROM.read(OPTIONS);
draw_Red = EEPROM.read(OPTIONS+1);
oled_screen.init();
oled_screen.fill(0x00);
draw_oled_screen(3);
delay(3000);
if (!max_sensor.begin()) {
draw_oled_screen(0);
while (1);
Serial.println("Finished setup");
}
max_sensor.setup();
attachInterrupt(digitalPinToInterrupt(BUTTON),button, CHANGE);
}
long lastBeat = 0; //Time of the last beat
long displaytime = 0; //Time of the last display update
bool led_on = false;
void loop() {
Serial.println("Starting loop");
sensors.requestTemperatures(); // Temperatur vom Sensor abrufen
float currentTempC = sensors.getTempCByIndex(0); // Temperatur in Celsius lesen
delay(10); // Add a short delay
oled_screen.drawStr(0,25,F("Temperature"),1);
print_digit(70,25,tempC);
oled_screen.drawStr(95,25,F("C"),1);
// Überprüfen, ob die Temperatur im gültigen Bereich liegt
if (currentTempC >= 0 && currentTempC <= 37.5) {
} else {
oled_screen.drawStr(10,0,F("Device error"),1);
}
max_sensor.check();
long now = millis(); //start time of this cycle
if (!max_sensor.available()) return;
uint32_t irValue = max_sensor.getIR();
uint32_t redValue = max_sensor.getRed();
max_sensor.nextSample();
if (irValue<5000) {
voltage = getVCC();
checkbutton();
draw_oled_screen(sleep_counter<=50 ? 1 : 4);
delay(200);
++sleep_counter;
if (sleep_counter>100) {
go_sleep();
sleep_counter = 0;
}
} else {
sleep_counter = 0;
int16_t IR_signal, Red_signal;
bool beatRed, beatIR;
if (!filter_for_graph) {
IR_signal = pulseIR.dc_filter(irValue) ;
Red_signal = pulseRed.dc_filter(redValue);
beatRed = pulseRed.isBeat(pulseRed.ma_filter(Red_signal));
beatIR = pulseIR.isBeat(pulseIR.ma_filter(IR_signal));
} else {
IR_signal = pulseIR.ma_filter(pulseIR.dc_filter(irValue)) ;
Red_signal = pulseRed.ma_filter(pulseRed.dc_filter(redValue));
beatRed = pulseRed.isBeat(Red_signal);
beatIR = pulseIR.isBeat(IR_signal);
}
wave.record(draw_Red ? -Red_signal : -IR_signal );
if (draw_Red ? beatRed : beatIR){
long btpm = 60000/(now - lastBeat);
if (btpm > 0 && btpm < 200) beatAvg = bpm.filter((int16_t)btpm);
lastBeat = now;
digitalWrite(LED, HIGH);
led_on = true;
long numerator = (pulseRed.avgAC() * pulseIR.avgDC())/256;
long denominator = (pulseRed.avgDC() * pulseIR.avgAC())/256;
int RX100 = (denominator>0) ? (numerator * 100)/denominator : 999;
SPO2f = (10400 - RX100*17+50)/100;
if ((RX100>=0) && (RX100<184))
SPO2 = pgm_read_byte_near(&spo2_table[RX100]);
}
if (now-displaytime>50) {
displaytime = now;
wave.scale();
draw_oled_screen(2);
}
Display_5();
}
if (led_on && (now - lastBeat)>25){
digitalWrite(LED, LOW);
led_on = false;
Serial.println("Finished loop");
}
}
Without Ds18b20 Sensor:
#include <avr/pgmspace.h>
#include <EEPROM.h>
#include <avr/sleep.h>
#include "ssd1306h.h"
#include "MAX30102.h"
#include "Pulse.h"
SSD1306 oled_screen;
MAX30102 max_sensor;
Pulse pulseIR;
Pulse pulseRed;
MAFilter bpm;
#define LED LED_BUILTIN
#define BUTTON 3
#define OPTIONS 7
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
static const uint8_t heart_bits[] PROGMEM = { 0x00, 0x00, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0xfe, 0xff,
0xfe, 0xff, 0xfc, 0x7f, 0xf8, 0x3f, 0xf0, 0x1f, 0xe0, 0x0f,
0xc0, 0x07, 0x80, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00 };
const uint8_t spo2_table[184] PROGMEM =
{ 95, 95, 95, 96, 96, 96, 97, 97, 97, 97, 97, 98, 98, 98, 98, 98, 99, 99, 99, 99,
99, 99, 99, 99, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 99, 99, 99, 99, 99, 99, 99, 99, 98, 98, 98, 98, 98, 98, 97, 97,
97, 97, 96, 96, 96, 96, 95, 95, 95, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91, 91,
90, 90, 89, 89, 89, 88, 88, 87, 87, 86, 86, 85, 85, 84, 84, 83, 82, 82, 81, 81,
80, 80, 79, 78, 78, 77, 76, 76, 75, 74, 74, 73, 72, 72, 71, 70, 69, 69, 68, 67,
66, 66, 65, 64, 63, 62, 62, 61, 60, 59, 58, 57, 56, 56, 55, 54, 53, 52, 51, 50,
49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 31, 30, 29,
28, 27, 26, 25, 23, 22, 21, 20, 19, 17, 16, 15, 14, 12, 11, 10, 9, 7, 6, 5,
3, 2, 1 } ;
int getVCC() {
#if defined(__AVR_ATmega1284P__)
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); // For ATmega1284
#else
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); // For ATmega328
#endif
delay(2); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA, ADSC));
uint8_t low = ADCL;
unsigned int val = (ADCH << 8) | low;
//discard previous result
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA, ADSC));
low = ADCL;
val = (ADCH << 8) | low;
return (((long)1024 * 1100) / val)/100;
}
void print_digit(int x, int y, long val, char c=' ', uint8_t field = 3,const int BIG = 1)
{
uint8_t ff = field;
do {
char ch = (val!=0) ? val%10+'0': c;
oled_screen.drawChar( x+BIG*(ff-1)*6, y, ch, BIG);
val = val/10;
--ff;
} while (ff>0);
}
const uint8_t MAXWAVE = 72;
class Waveform {
public:
Waveform(void) {wavep = 0;}
void record(int waveval) {
waveval = waveval/8;
waveval += 128;
waveval = waveval<0? 0 : waveval;
waveform[wavep] = (uint8_t) (waveval>255)?255:waveval;
wavep = (wavep+1) % MAXWAVE;
}
void scale() {
uint8_t maxw = 0;
uint8_t minw = 255;
for (int i=0; i<MAXWAVE; i++) {
maxw = waveform[i]>maxw?waveform[i]:maxw;
minw = waveform[i]<minw?waveform[i]:minw;
}
uint8_t scale8 = (maxw-minw)/4 + 1;
uint8_t index = wavep;
for (int i=0; i<MAXWAVE; i++) {
disp_wave[i] = 31-((uint16_t)(waveform[index]-minw)*8)/scale8;
index = (index + 1) % MAXWAVE;
}
}
void draw(uint8_t X) {
for (int i=0; i<MAXWAVE; i++) {
uint8_t y = disp_wave[i];
oled_screen.drawPixel(X+i, y);
if (i<MAXWAVE-1) {
uint8_t nexty = disp_wave[i+1];
if (nexty>y) {
for (uint8_t iy = y+1; iy<nexty; ++iy)
oled_screen.drawPixel(X+i, iy);
}
else if (nexty<y) {
for (uint8_t iy = nexty+1; iy<y; ++iy)
oled_screen.drawPixel(X+i, iy);
}
}
}
}
private:
uint8_t waveform[MAXWAVE];
uint8_t disp_wave[MAXWAVE];
uint8_t wavep = 0;
} wave;
int beatAvg;
int SPO2, SPO2f;
int voltage;
bool filter_for_graph = false;
bool draw_Red = false;
uint8_t pcflag =0;
uint8_t istate = 0;
uint8_t sleep_counter = 0;
void button(void){
pcflag = 1;
}
void checkbutton(){
if (pcflag && !digitalRead(BUTTON)) {
istate = (istate +1) % 4;
filter_for_graph = istate & 0x01;
draw_Red = istate & 0x02;
EEPROM.write(OPTIONS, filter_for_graph);
EEPROM.write(OPTIONS+1, draw_Red);
}
pcflag = 0;
}
void Display_5(){
if(pcflag && !digitalRead(BUTTON)){
draw_oled_screen(5);
delay(1100);
}
pcflag = 0;
}
void go_sleep() {
oled_screen.fill(0);
oled_screen.off();
delay(10);
max_sensor.off();
delay(10);
cbi(ADCSRA, ADEN);
delay(10);
pinMode(0,INPUT);
pinMode(2,INPUT);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_mode();
// cause reset
setup();
}
void draw_oled_screen(int msg) {
oled_screen.firstPage();
do{
switch(msg){
case 0: oled_screen.drawStr(10,0,F("Device error"),1);
break;
case 1: oled_screen.drawStr(35,7,F("PLACE YOUR"),1);
oled_screen.drawStr(45,17,F("FINGER"),1);
break;
case 2: oled_screen.drawStr(0,0,F("Pulse Rate"),1);
print_digit(70,0,beatAvg);
oled_screen.drawStr(95,0,F("BPM"),1);
oled_screen.drawStr(15,10,F("Oxygen"),1);
oled_screen.drawStr(0,17,F("Saturation"),1);
print_digit(70,15,SPO2f,' ',3,1);
oled_screen.drawChar(95,15,'%',1);
break;
case 3: oled_screen.drawStr(0,8,F("BA - Patientenmonitor"),1);
oled_screen.drawStr(55,20,F("GE"),1);
break;
case 4: oled_screen.drawStr(28,12,F("OFF IN"),1);
oled_screen.drawChar(76,12,10-sleep_counter/10+'0');
oled_screen.drawChar(82,12,'s');
break;
case 5: oled_screen.drawStr(0,0,F("AVG Pulse"),1);
print_digit(70,0,beatAvg);
oled_screen.drawStr(95,0,F("BPM"),1);
oled_screen.drawStr(0,10,F("AVG Oxygen"),1);
oled_screen.drawStr(0,17,F("Saturation"),1);
print_digit(70,15,SPO2);
oled_screen.drawChar(95,15,'%',1);
break;
}
} while (oled_screen.nextPage());
}
void setup(void) {
pinMode(LED, OUTPUT);
pinMode(BUTTON, INPUT_PULLUP);
filter_for_graph = EEPROM.read(OPTIONS);
draw_Red = EEPROM.read(OPTIONS+1);
oled_screen.init();
oled_screen.fill(0x00);
draw_oled_screen(3);
delay(3000);
if (!max_sensor.begin()) {
draw_oled_screen(0);
while (1);
}
max_sensor.setup();
attachInterrupt(digitalPinToInterrupt(BUTTON),button, CHANGE);
}
long lastBeat = 0; //Time of the last beat
long displaytime = 0; //Time of the last display update
bool led_on = false;
void loop() {
max_sensor.check();
long now = millis(); //start time of this cycle
if (!max_sensor.available()) return;
uint32_t irValue = max_sensor.getIR();
uint32_t redValue = max_sensor.getRed();
max_sensor.nextSample();
if (irValue<5000) {
voltage = getVCC();
checkbutton();
draw_oled_screen(sleep_counter<=50 ? 1 : 4);
delay(200);
++sleep_counter;
if (sleep_counter>100) {
go_sleep();
sleep_counter = 0;
}
} else {
sleep_counter = 0;
int16_t IR_signal, Red_signal;
bool beatRed, beatIR;
if (!filter_for_graph) {
IR_signal = pulseIR.dc_filter(irValue) ;
Red_signal = pulseRed.dc_filter(redValue);
beatRed = pulseRed.isBeat(pulseRed.ma_filter(Red_signal));
beatIR = pulseIR.isBeat(pulseIR.ma_filter(IR_signal));
} else {
IR_signal = pulseIR.ma_filter(pulseIR.dc_filter(irValue)) ;
Red_signal = pulseRed.ma_filter(pulseRed.dc_filter(redValue));
beatRed = pulseRed.isBeat(Red_signal);
beatIR = pulseIR.isBeat(IR_signal);
}
wave.record(draw_Red ? -Red_signal : -IR_signal );
if (draw_Red ? beatRed : beatIR){
long btpm = 60000/(now - lastBeat);
if (btpm > 0 && btpm < 200) beatAvg = bpm.filter((int16_t)btpm);
lastBeat = now;
digitalWrite(LED, HIGH);
led_on = true;
long numerator = (pulseRed.avgAC() * pulseIR.avgDC())/256;
long denominator = (pulseRed.avgDC() * pulseIR.avgAC())/256;
int RX100 = (denominator>0) ? (numerator * 100)/denominator : 999;
SPO2f = (10400 - RX100*17+50)/100;
if ((RX100>=0) && (RX100<184))
SPO2 = pgm_read_byte_near(&spo2_table[RX100]);
}
if (now-displaytime>50) {
displaytime = now;
wave.scale();
draw_oled_screen(2);
}
Display_5();
}
if (led_on && (now - lastBeat)>25){
digitalWrite(LED, LOW);
led_on = false;
}
}


