ich würde gerne einen Sketch umschreiben und hierbei die Classen verwenden. Der Sketch funktioniert ohne Klassen/ Objekte, aber beim umschreiben kommen noch falsche Werte serial raus. Kurz die Funktion: Ein Objekt soll einen Zyklus von 10 Sekunden haben und hierbei den Durchschnittswert ermitteln. Dazu werden die Durchläufe gezählt und die Werte des Sensors pro Durchlauf addiert, nach 10 Sekunden wird nun mein gesammelter Wert durch die Durchläufe dividiert. Wenn das klappt würde ich gerne noch ein Struct einbauen.
Hier mein Versuch:
#include <Wire.h>
#include "MAX30105.h"
MAX30105 particleSensor;
#define debug Serial //Uncomment this line if you're using an Uno or ESP
//#define debug SerialUSB //Uncomment this line if you're using a SAMD21
void setup()
{
debug.begin(9600);
debug.println("MAX30105 Basic Readings Example");
// Initialize sensor
if (particleSensor.begin() == false)
{
debug.println("MAX30105 was not found. Please check wiring/power. ");
while (1);
}
particleSensor.setup(); //Configure sensor. Use 6.4mA for LED drive
}
void loop()
{
debug.print(" R[");
debug.print(particleSensor.getRed());
debug.print("] IR[");
debug.print(particleSensor.getIR());
debug.print("] G[");
debug.print(particleSensor.getGreen());
debug.print("]");
debug.println();
class ZyklusSPO2 { // Definition der Klasse ZyklusSPO2
private:
const long interval = 10000;
public:
float total_per_cycle = 0; //Variablendeklaration
float average_per_cycle = 0; //Variablendeklaration
ZyklusSPO2() { // Konstukter
}
unsigned long currentMillis = millis();
unsigned long previousMillis = 0; // Aufrud der Zeitfunktion des ESP
int cycle = 0;
float average() {
if (currentMillis - previousMillis <= interval)
{
total_per_cycle = total_per_cycle + particleSensor.getRed();
cycle = cycle + 1;
}
else
{
average_per_cycle = total_per_cycle/cycle;
cycle = 0;
total_per_cycle = 0;
previousMillis = currentMillis; //Zurücksetzen meines gespeicherten Zeitstempels
return average_per_cycle;
}
}
};
ZyklusSPO2 erstesObjekt; //Erzeugt ein erstes Objekt der Klasse ZyklusSPO2
//ZyklusSPO2 erstesObjekt = ZyklusSPO2();
float wert = erstesObjekt.average(); // Gibt den Wert der Funktion average des Objektes der Klasse ZyklusSPO2 aus
Serial.print("Durchschnittlicher Wert = ");
Serial.print(wert);
int Zykluszaeler;
Zykluszaeler = erstesObjekt.cycle; //greift auf die Zyklus Variable des ersten Objektes der Klasse ZyklusPO2 zu
Serial.print("Zyklus = ");
Serial.print(Zykluszaeler);
Serial.print("Zeit = ");
Serial.print(erstesObjekt.currentMillis);
Serial.print("Vorherige Zeit = ");
Serial.print(erstesObjekt.currentMillis);
}
Beim Durchschnittlichen Wert kommt nan raus, ev weil ich mit 0 initialisiere und das Objekt immer neu aufgebaut und zerstört wird? Können Objekte bestehen bleiben? Zyklus ist immer 0 und meine Zeit ist die vorherige und die aktuelle immer gleich.
Das ist die Definition einer public member Variablen. Je nachdem, ob die Instanz lokal in loop oder global erzeugt wird, liefert millis() unterschiedliche bis evtl. sinnlose Werte.
Das ist normalerweise (und hier in deinem Beispiel offensichtlich) Sinn des ganzen.
Die Klassendefinition gehört sowieso außerhalb von loop.
Die Erzeugung einer Instanz dieser Klasse im einfachsten Fall ebenfalls global.
Dabei bedenken, dass dies SEHR früh geschieht, lange bevor setup() läuft. Wenn man Initialisierungs-Sachen erst zu einem definierten Zeitpunkt laufen lassen möchte, packt man dies in eine Methode namens init() oder begin() und ruft diese üblicherweise in setup() auf.
Meist haben solche Klassen auch eine Methode (gerne run() genannt), die von loop() so oft wie möglich aufgerufen wird und selber entscheidet, was wie oft ausgeführt werden soll, oder dass aktuell nichts zu tun ist.
Danke für eure freundliche Unterstützung! Ich habe nun einmal meine Klasse und das Objekt global eingefügt, nur leider bekomme ich immer noch nicht das raus was ich gerne hätte, hier mein neuer Versuch:
#include <Wire.h>
#include "MAX30105.h"
MAX30105 particleSensor;
#define debug Serial //Uncomment this line if you're using an Uno or ESP
//#define debug SerialUSB //Uncomment this line if you're using a SAMD21
class ZyklusSPO2 { // Definition der Klasse ZyklusSPO2
private:
float total_per_cycle = 0; //Variablendeklaration
float average_per_cycle = 0; //Variablendeklaration
const long interval = 10000;
public:
ZyklusSPO2() { // Konstukter
}
unsigned long currentMillis = millis();
unsigned long previousMillis = 0; // Aufrud der Zeitfunktion des ESP
int cycle = 0;
float average() {
if (currentMillis - previousMillis <= interval)
{
total_per_cycle = total_per_cycle + particleSensor.getRed();
cycle = cycle + 1;
}
else
{
average_per_cycle = total_per_cycle/cycle;
cycle = 0;
total_per_cycle = 0;
previousMillis = currentMillis; //Zurücksetzen meines gespeicherten Zeitstempels
return average_per_cycle;
}
}
};
ZyklusSPO2 erstesObjekt; //Erzeugt ein erstes Objekt der Klasse ZyklusSPO2
void setup()
{
debug.begin(9600);
debug.println("MAX30105 Basic Readings Example");
// Initialize sensor
if (particleSensor.begin() == false)
{
debug.println("MAX30105 was not found. Please check wiring/power. ");
while (1);
}
particleSensor.setup(); //Configure sensor. Use 6.4mA for LED drive
}
void loop()
{
debug.print(" R[");
debug.print(particleSensor.getRed());
debug.print("] IR[");
debug.print(particleSensor.getIR());
debug.print("] G[");
debug.print(particleSensor.getGreen());
debug.print("]");
debug.println();
//ZyklusSPO2 erstesObjekt = ZyklusSPO2();
float wert = erstesObjekt.average(); // Gibt den Wert der Funktion average des Objektes der Klasse ZyklusSPO2 aus
Serial.print("Durchschnittlicher Wert = ");
Serial.print(wert);
int Zykluszaeler;
Zykluszaeler = erstesObjekt.cycle; //greift auf die Zyklus Variable des ersten Objektes der Klasse ZyklusPO2 zu
Serial.print("Zyklus = ");
Serial.print(Zykluszaeler);
Serial.print("Zeit = ");
Serial.print(erstesObjekt.currentMillis);
Serial.print("Vorherige Zeit = ");
Serial.print(erstesObjekt.currentMillis);
}
#include <Wire.h>
#include "MAX30105.h"
MAX30105 particleSensor;
#define debug Serial //Uncomment this line if you're using an Uno or ESP
//#define debug SerialUSB //Uncomment this line if you're using a SAMD21
class ZyklusSPO2 { // Definition der Klasse ZyklusSPO2
public:
const long interval = 10000;
float total_per_cycle = 0;
unsigned long previousMillis = 0;
unsigned int cycle = 0;
float average() ;
float average_per_cycle = 0;
};
float ZyklusSPO2::average() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis <= interval) {
total_per_cycle = total_per_cycle + particleSensor.getRed();
cycle = cycle + 1;
} else if (cycle > 0) {
average_per_cycle = total_per_cycle/cycle;
cycle = 0;
total_per_cycle = 0;
previousMillis = currentMillis;
}
return average_per_cycle; // liefert den letzten errechneten Wert zurück
}
ZyklusSPO2 erstesObjekt; //Erzeugt ein erstes Objekt der Klasse ZyklusSPO2
}
void setup()
{
debug.begin(9600);
debug.println("MAX30105 Basic Readings Example");
// Initialize sensor
if (particleSensor.begin() == false)
{
debug.println("MAX30105 was not found. Please check wiring/power. ");
while (1);
}
particleSensor.setup(); //Configure sensor. Use 6.4mA for LED drive
}
void loop()
{
Serial.print("Durchschnitt pro Zyklus:");
Serial.print(erstesObjekt.average());
Jetzt hätte ich meinen Sketch in eine .h und eine .cpp aufgeteilt die ich filters.h und filters.cpp genannt habe:
Libary um verschiedene Filter für den MAX 30102 einzubinden und
bestimmte Werte zu berechnen. (zB Durchschnittlichen Wert pro Zeitinterwall).
Erstellt am 16.04.23 by I.T.
*/
#include "Arduino.h"
#ifndef filters_h
#define filters_h
class ZyklusSPO2 { // Definition der Klasse ZyklusSPO2
public:
const long interval = 10000;
float total_per_cycle = 0;
unsigned long previousMillis = 0;
unsigned int cycle = 0;
float average() ;
float average_per_cycle = 0;
};
#endif
Leider bekomme ich nun einen Error:
C:\Users\emanu\Documents\Arduino\libraries\DFRobot_MAX30102-master\src\filters.cpp: In member function 'float ZyklusSPO2::average()':
filters.cpp:17:45: error: 'particleSensor' was not declared in this scope
total_per_cycle = total_per_cycle + particleSensor.getRed();
^
exit status 1
'particleSensor' was not declared in this scope
Ich glaube, Du hast die Grundlagen von OOP noch nicht verstanden.
Erstes Pradigma ist Kapseln, d.h. die Instanzvariablen sind nicht public, sondern private oder evtl. (in speziellen Fällen) protected.
Zugriff auf die Instanzvariablen über Getter und Setter und Methoden der Klasse.
Nein, sehe ich so auch nicht. Tommys Bemerkung ist zwar generell richtig, hat aber nichts mit deinem Problem zu tun.
Vermutlich geht irgendwas mit deinen .ino , .cpp und .h Dateien durcheinander. Hast du außer der filters.cpp im libraries/DFRobot... Verzeichnis noch andere Kandidaten, die du uns gezeigt hast, die aber nicht vom Compiler verwendet werden (oder umgekehrt?)
ja mit get und set hab ich noch nicht gearbeitet, das habe ich nun aber vor, danke für den Tipp.
Meine bisherige Idee zu dem Problem:
Der Versuch den ich jetzt unternehmen werde sieht wie folgt aus. Ich werde der Klasse SPO2Zyklus die Funktion setSensorwert_rot hinzufügen und den Sensorwert_rot in die CPP einfügen (anstatt dort auf den particleSensor zu verweisen) und dann in meinem Sketch bei dem Objekt "erstes Objekt" den Sensowert_rot = particleSensor.getRed definieren.
#include <DFRobot_MAX30102.h>
#include "filters.h"
DFRobot_MAX30102 particleSensor;
ZyklusSPO2 erstesObjekt; //Erzeugt ein erstes Objekt der Klasse ZyklusSPO2
erstesObjekt.Sensorwert(particleSensor.getRed());
/*
Macro definition opions in sensor configuration
sampleAverage: SAMPLEAVG_1 SAMPLEAVG_2 SAMPLEAVG_4
SAMPLEAVG_8 SAMPLEAVG_16 SAMPLEAVG_32
ledMode: MODE_REDONLY MODE_RED_IR MODE_MULTILED
sampleRate: PULSEWIDTH_69 PULSEWIDTH_118 PULSEWIDTH_215 PULSEWIDTH_411
pulseWidth: SAMPLERATE_50 SAMPLERATE_100 SAMPLERATE_200 SAMPLERATE_400
SAMPLERATE_800 SAMPLERATE_1000 SAMPLERATE_1600 SAMPLERATE_3200
adcRange: ADCRANGE_2048 ADCRANGE_4096 ADCRANGE_8192 ADCRANGE_16384
*/
void setup()
{
//Init serial
Serial.begin(115200);
/*!
*@brief Init sensor
*@param pWire IIC bus pointer object and construction device, can both pass or not pass parameters (Wire in default)
*@param i2cAddr Chip IIC address (0x57 in default)
*@return true or false
*/
while (!particleSensor.begin()) {
Serial.println("MAX30102 was not found");
delay(1000);
}
/*!
*@brief Use macro definition to configure sensor
*@param ledBrightness LED brightness, default value: 0x1F(6.4mA), Range: 0~255(0=Off, 255=50mA)
*@param sampleAverage Average multiple samples then draw once, reduce data throughput, default 4 samples average
*@param ledMode LED mode, default to use red light and IR at the same time
*@param sampleRate Sampling rate, default 400 samples every second
*@param pulseWidth Pulse width: the longer the pulse width, the wider the detection range. Default to be Max range
*@param adcRange Measurement Range, default 4096 (nA), 15.63(pA) per LSB
*/
particleSensor.sensorConfiguration(/*ledBrightness=*/0x1F, /*sampleAverage=*/SAMPLEAVG_4, \
/*ledMode=*/MODE_MULTILED, /*sampleRate=*/SAMPLERATE_400, \
/*pulseWidth=*/PULSEWIDTH_411, /*adcRange=*/ADCRANGE_4096);
}
void loop()
{
//Print result
Serial.print("Durchschnitt pro 10 Sekunden =");
Serial.print(erstesObjekt.average());
}
/*
Libary um verschiedene Filter für den MAX 30102 einzubinden und
bestimmte Werte zu berechnen. (zB Durchschnittlichen Wert pro Zeitinterwall).
Erstellt am 16.04.23 by I.T.
*/
#include "Arduino.h"
#include "filters.h"
void ZyklusSPO2::setSensorwert(uint16_t sw){
Sensorwert = sw;
}
float ZyklusSPO2::average() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis <= interval) {
total_per_cycle = total_per_cycle + Sensorwert;
cycle = cycle + 1;
} else if (cycle > 0) {
average_per_cycle = total_per_cycle/cycle;
cycle = 0;
total_per_cycle = 0;
previousMillis = currentMillis;
}
return average_per_cycle; // liefert den letzten errechneten Wert zurück
}
/*
Libary um verschiedene Filter für den MAX 30102 einzubinden und
bestimmte Werte zu berechnen. (zB Durchschnittlichen Wert pro Zeitinterwall).
Erstellt am 16.04.23 by I.T.
*/
#include "Arduino.h"
#ifndef filters_h
#define filters_h
class ZyklusSPO2 { // Definition der Klasse ZyklusSPO2
public:
const long interval = 10000;
float total_per_cycle = 0;
void setSensorwert(uint16_t Sensorwert);
unsigned long previousMillis = 0;
unsigned int cycle = 0;
float average() ;
float average_per_cycle = 0;
};
#endif
Leider hab ich da immer noch ähnliche Errors:
C:\Users\emanu\AppData\Local\Temp\arduino_modified_sketch_77463\filters.cpp: In member function 'void ZyklusSPO2::setSensorwert(uint16_t)':
filters.cpp:16:5: error: 'Sensorwert' was not declared in this scope
Sensorwert = sw;
^
C:\Users\emanu\AppData\Local\Temp\arduino_modified_sketch_77463\filters.cpp: In member function 'float ZyklusSPO2::average()':
filters.cpp:26:45: error: 'Sensorwert' was not declared in this scope
total_per_cycle = total_per_cycle + Sensorwert;
^
basicRead:8:1: error: 'erstesObjekt' does not name a type
erstesObjekt.Sensorwert(particleSensor.getRed());
^
exit status 1
'Sensorwert' was not declared in this scope
Wenn ich mich jetzt nicht irre kann ich auch ohne set eine get Funktion in der Klasse definieren und es dann so schreiben? ZyklusSPO2 erstesObjekt (particleSensor.getRed());
#include <DFRobot_MAX30102.h>
#include "filters.h"
DFRobot_MAX30102 particleSensor;
ZyklusSPO2 erstesObjekt; //Erzeugt ein erstes Objekt der Klasse ZyklusSPO2
/*
Macro definition opions in sensor configuration
sampleAverage: SAMPLEAVG_1 SAMPLEAVG_2 SAMPLEAVG_4
SAMPLEAVG_8 SAMPLEAVG_16 SAMPLEAVG_32
ledMode: MODE_REDONLY MODE_RED_IR MODE_MULTILED
sampleRate: PULSEWIDTH_69 PULSEWIDTH_118 PULSEWIDTH_215 PULSEWIDTH_411
pulseWidth: SAMPLERATE_50 SAMPLERATE_100 SAMPLERATE_200 SAMPLERATE_400
SAMPLERATE_800 SAMPLERATE_1000 SAMPLERATE_1600 SAMPLERATE_3200
adcRange: ADCRANGE_2048 ADCRANGE_4096 ADCRANGE_8192 ADCRANGE_16384
*/
void setup()
{
//Init serial
Serial.begin(115200);
/*!
*@brief Init sensor
*@param pWire IIC bus pointer object and construction device, can both pass or not pass parameters (Wire in default)
*@param i2cAddr Chip IIC address (0x57 in default)
*@return true or false
*/
while (!particleSensor.begin()) {
Serial.println("MAX30102 was not found");
delay(1000);
}
/*!
*@brief Use macro definition to configure sensor
*@param ledBrightness LED brightness, default value: 0x1F(6.4mA), Range: 0~255(0=Off, 255=50mA)
*@param sampleAverage Average multiple samples then draw once, reduce data throughput, default 4 samples average
*@param ledMode LED mode, default to use red light and IR at the same time
*@param sampleRate Sampling rate, default 400 samples every second
*@param pulseWidth Pulse width: the longer the pulse width, the wider the detection range. Default to be Max range
*@param adcRange Measurement Range, default 4096 (nA), 15.63(pA) per LSB
*/
particleSensor.sensorConfiguration(/*ledBrightness=*/0x1F, /*sampleAverage=*/SAMPLEAVG_4, \
/*ledMode=*/MODE_MULTILED, /*sampleRate=*/SAMPLERATE_400, \
/*pulseWidth=*/PULSEWIDTH_411, /*adcRange=*/ADCRANGE_4096);
}
void loop()
{
//Print result
Serial.println("Durchschnitt pro 10 Sekunden =");
Serial.println(erstesObjekt.average());
erstesObjekt.setSensorwert (particleSensor.getRed());
}
/*
Libary um verschiedene Filter für den MAX 30102 einzubinden und
bestimmte Werte zu berechnen. (zB Durchschnittlichen Wert pro Zeitinterwall).
Erstellt am 16.04.23 by I.T.
*/
#include "Arduino.h"
#include "filters.h"
void ZyklusSPO2::setSensorwert(uint16_t sw){
Sensorwert = sw;
}
// uint16_t ZyklusSPO2::getSensorwert(){
// return Sensorwert;
// }
float ZyklusSPO2::average() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis <= interval) {
total_per_cycle = total_per_cycle + Sensorwert;
cycle = cycle + 1;
} else if (cycle > 0) {
average_per_cycle = total_per_cycle/cycle;
cycle = 0;
total_per_cycle = 0;
previousMillis = currentMillis;
}
return average_per_cycle; // liefert den letzten errechneten Wert zurück
}
/*
Libary um verschiedene
/*
Libary um verschiedene Filter für den MAX 30102 einzubinden und
bestimmte Werte zu berechnen. (zB Durchschnittlichen Wert pro Zeitinterwall).
Erstellt am 16.04.23 by I.T.
*/
#include "Arduino.h"
#ifndef filters_h
#define filters_h
class ZyklusSPO2 { // Definition der Klasse ZyklusSPO2
public:
const long interval = 10000;
float total_per_cycle = 0;
void setSensorwert(uint16_t Sensorwert);
unsigned long previousMillis = 0;
unsigned int cycle = 0;
float average() ;
float average_per_cycle = 0;
private:
float Sensorwert;
};
#endif