Probleme beim Zusammenführen von 2 Sketches

Hallo Forum,

mein Name ist Martin,ich bin lernwilliger Arduinoanfänger und stehe vor einem Problem das ich alleine nicht gelöst bekomme.

Ich habe 2 Sketche die unabhängig voneinander funktionieren. Füge ich jedoch Sketch 1 und 2 zusammen zu einem Programm funktioniert nur noch Sketch 1.

Konkret geht es darum verschiedene Spannungen und Ströme zu messen und auf LCD Displays anzuzeigen (Sketch 1) und gleichzeitig auch noch einen PWM Leistungssteller durch einen Drehencoder anzusteuern mit 0-5V (Sketch 2).

Ich habe die Sketches unabhängig voneinander geschrieben bzw. auf Beispiele zurückgegriffen und erfolgreich getestet. Falsche Verdrahtung kann ich ausschließen, es muss an der Software liegen.

Auch einen Fehler durch Copy & Paste kann ich ausschließen da ich den Code von Sketch 2 probehalber auch noch von Hand geschrieben habe.

Vielleicht kann von euch mal jemand über den Sketch drüberschauen und mir auf die Sprünge helfen.

>
#include <RotaryEncoder.h>

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd1(0x23, 16, 2); // 3,3V
LiquidCrystal_I2C lcd2(0x24, 16, 2); // 5V
LiquidCrystal_I2C lcd3(0x25, 16, 2); // 12V
LiquidCrystal_I2C lcd4(0x26, 16, 2); // 24V
LiquidCrystal_I2C lcd5(0x27, 16, 2); // PWM


#define ROTARYSTEPS 5
#define ROTARYMIN 0
#define ROTARYMAX 100



RotaryEncoder encoder(A11, A12);  // Setup a RotaryEncoder for pins A11 and A12:


int lastPos = -1; // Last known rotary position.
int PWM_Pin = 3;
int PWM = 0;

const int analogIn_Vcc = A0;
const int analogIn_U3V3 = A1;
const int analogIn_I3V3 = A2;
const int analogIn_U5V = A3;
const int analogIn_I5V = A4;
const int analogIn_U12V = A5;
const int analogIn_I12V = A6;
const int analogIn_U24V = A7;
const int analogIn_I24V = A8;


const float U_ref = 1.1; // in V
const float R0 = 52.5; //  100 kOhm Potis zum Abgleich für alle Spannungen
const float R1 = 219.7; // in kOhm für 3V3 + 5V + Vcc
const float R2 = 560.0; // in kOhm für 12V
const float R3 = 1100.0; // in kOhm für 24v

const int averages = 25; // Mittelwert aus 25 Messungen

float ACSoffset; // Offsetspannung von ACS712 Stromsensor = Vcc/2

float voltageVcc;
float voltageU3V3;
float voltageI3V3;
float voltageU5V;
float voltageI5V;
float voltageU12V;
float voltageI12V;
float voltageU24V;
float voltageI24V;

int ADC_countVcc;
int ADC_countU3V3;
int ADC_countI3V3;
int ADC_countU5V;
int ADC_countI5V;
int ADC_countU12V;
int ADC_countI12V;
int ADC_countU24V;
int ADC_countI24V;

float AmpsI3V3;
float AmpsI5V;
float AmpsI12V;
float AmpsI24V;

float Watt3V3;
float Watt5V;
float Watt12V;
float Watt24V;




void setup() {


  encoder.setPosition(0 / ROTARYSTEPS); // start with the value of 0.

  Serial.begin(9600);
  analogReference(INTERNAL1V1);
  lcd1.begin();
  lcd1.backlight();
  lcd2.begin();
  lcd2.backlight();
  lcd3.begin();
  lcd3.backlight();
  lcd4.begin();
  lcd4.backlight();
  lcd5.begin();
  lcd5.backlight();



}


void messung_Vcc() {

  ADC_countVcc = 0;
  for (int i = 0; i < averages; i++)
    ADC_countVcc += analogRead(analogIn_Vcc);
  voltageVcc = (R1 + R0) / R0 * U_ref * ADC_countVcc / 1023 / averages;

}

void messung_5V() {

  ADC_countU5V = 0;
  for (int i = 0; i < averages; i++)
    ADC_countU5V += analogRead(analogIn_U5V);
  voltageU5V = (R1 + R0) / R0 * U_ref * ADC_countU5V / 1023 / averages;

  ADC_countI5V = 0;
  for (int i = 0; i < averages; i++)
    ADC_countI5V += analogRead(analogIn_I5V);
  voltageI5V = (R1 + R0) / R0 * U_ref * ADC_countI5V / 1023 / averages;
  ACSoffset = voltageVcc * 0.5;
  AmpsI5V = (voltageI5V - ACSoffset) / 0.066;

  Watt5V = voltageU5V * AmpsI5V;

}

void messung_3V3() {

  ADC_countU3V3 = 0;
  for (int i = 0; i < averages; i++)
    ADC_countU3V3 += analogRead(analogIn_U3V3);
  voltageU3V3 = (R1 + R0) / R0 * U_ref * ADC_countU3V3 / 1023 / averages;

  ADC_countI3V3 = 0;
  for (int i = 0; i < averages; i++)
    ADC_countI3V3 += analogRead(analogIn_I3V3);
  voltageI3V3 = (R1 + R0) / R0 * U_ref * ADC_countI3V3 / 1023 / averages;
  ACSoffset = voltageVcc * 0.5;
  AmpsI3V3 = (voltageI3V3 - ACSoffset) / 0.066;

  Watt3V3 = voltageU3V3 * AmpsI3V3;

}

void messung_12V() {

  ADC_countU12V = 0;
  for (int i = 0; i < averages; i++)
    ADC_countU12V += analogRead(analogIn_U12V);
  voltageU12V = (R2 + R0) / R0 * U_ref * ADC_countU12V / 1023 / averages;

  ADC_countI12V = 0;
  for (int i = 0; i < averages; i++)
    ADC_countI12V += analogRead(analogIn_I12V);
  voltageI12V = (R1 + R0) / R0 * U_ref * ADC_countI12V / 1023 / averages;
  ACSoffset = voltageVcc * 0.5;
  AmpsI12V = (voltageI12V - ACSoffset) / 0.066;

  Watt12V = voltageU12V * AmpsI12V;

}

void messung_24V() {

  ADC_countU24V = 0;
  for (int i = 0; i < averages; i++)
    ADC_countU24V += analogRead(analogIn_U24V);
  voltageU24V = (R3 + R0) / R0 * U_ref * ADC_countU12V / 1023 / averages;

  ADC_countI24V = 0;
  for (int i = 0; i < averages; i++)
    ADC_countI24V += analogRead(analogIn_I24V);
  voltageI24V = (R1 + R0) / R0 * U_ref * ADC_countI24V / 1023 / averages;
  ACSoffset = voltageVcc * 0.5;
  AmpsI24V = (voltageI24V - ACSoffset) / 0.066;

  Watt24V = voltageU24V * AmpsI24V;

}

void loop() {

  encoder.tick();

  // get the current physical position and calc the logical position
  int newPos = encoder.getPosition() * ROTARYSTEPS;

  analogWrite(PWM_Pin, PWM);


  if (newPos < ROTARYMIN) {
    encoder.setPosition(ROTARYMIN / ROTARYSTEPS);
    newPos = ROTARYMIN;
  }


  else if (newPos > ROTARYMAX) {
    encoder.setPosition(ROTARYMAX / ROTARYSTEPS);
    newPos = ROTARYMAX;
  }


  if (lastPos != newPos) {
    Serial.print(newPos);
    Serial.println();
    lastPos = newPos;
  }

  PWM = map(newPos, 0, 100, 0, 255);


  lcd5.setCursor(0, 0);
  lcd5.print(newPos);
  lcd5.println(" Prozent");

  messung_5V();
  messung_Vcc();
  messung_3V3();
  messung_12V();
  messung_24V();



  lcd1.setCursor(0, 0);
  lcd1.print("U=");
  lcd1.print(voltageU5V, 1);
  lcd1.print(" V");
  lcd1.setCursor(0, 1);
  lcd1.print("I=");
  lcd1.print(AmpsI5V, 2);
  lcd1.print(" A");
  lcd1.setCursor(9, 1);
  lcd1.print("P=");
  lcd1.print(Watt5V, 1);
  lcd1.print(" W");





  delay(1000);
}


<

Da hier keiner weiß, was bei Dir Sketch 1 und was Sketch 2 ist, solltest Du schon etwas genauer beschreiben, was passiert und was nicht.

Ich habe den Verdacht, dass Deine for-Schleifen den Code zu lange blockieren.

Gruß Tommy

Hi

Verstehe ich Dich recht: Du willst 5 verschiedene Messungen auf 5 verschiedenen LCD darstellen?

Da wirst Du bei Uno und Nano das Problem haben, daß A4 und A5 für I²C gebraucht werden - auf diesen Pins ist entweder Analog-IN, oder I²C möglich.
Allerdings schreibst Du, daß die Sketche alleine laufen - somit wird's wohl kein Uno/Nano sein, oder?

Sketch 2 ist nicht mit in den Post gekommen?

MfG

Sorry wenn ich mich unklar ausgedrückt habe! Sketch 1 sind die ganzen Strom/Spannungsmessungen, Sketch 2 ist die PWM Steuerung. Der angehängete Code aus dem ersten Post sind beide Sketches zusammengeführt.

Die Strom/Spannungsmessung funktioniert auch nach der Zusammenführung, aber die Impulse vom Drehencoder werden nicht erkannt. Lade ich dann nur den PWM Sketch 2 hoch funktioniert die PWM Steuerung (ohne an der Verdrahtung etwas zu ändern).

Richtig, ich will für jede Spannung (3,3V; 5V; 12V; 24V; 24V PWM) ein LCD Display wo ich mir die Werte anzeigen lasse. Als Board verwende ich ein Arduino Mega 2560 Clone.

Hier nochmal beide Sketches einzeln:

Sketch 1 (Strom/Spannungsmessungen)

[code]


#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd1(0x23, 16, 2); // 3,3V
LiquidCrystal_I2C lcd2(0x24, 16, 2); // 5V
LiquidCrystal_I2C lcd3(0x25, 16, 2); // 12V
LiquidCrystal_I2C lcd4(0x26, 16, 2); // 24V
LiquidCrystal_I2C lcd5(0x27, 16, 2); // PWM










const int analogIn_Vcc = A0;
const int analogIn_U3V3 = A1;
const int analogIn_I3V3 = A2;
const int analogIn_U5V = A3;
const int analogIn_I5V = A4;
const int analogIn_U12V = A5;
const int analogIn_I12V = A6;
const int analogIn_U24V = A7;
const int analogIn_I24V = A8;


const float U_ref = 1.1; // in V
const float R0 = 52.5; //  100 kOhm Potis zum Abgleich für alle Spannungen
const float R1 = 219.7; // in kOhm für 3V3 + 5V + Vcc
const float R2 = 560.0; // in kOhm für 12V
const float R3 = 1100.0; // in kOhm für 24v

const int averages = 25; // Mittelwert aus 25 Messungen

float ACSoffset; // Offsetspannung von ACS712 Stromsensor = Vcc/2

float voltageVcc;
float voltageU3V3;
float voltageI3V3;
float voltageU5V;
float voltageI5V;
float voltageU12V;
float voltageI12V;
float voltageU24V;
float voltageI24V;

int ADC_countVcc;
int ADC_countU3V3;
int ADC_countI3V3;
int ADC_countU5V;
int ADC_countI5V;
int ADC_countU12V;
int ADC_countI12V;
int ADC_countU24V;
int ADC_countI24V;

float AmpsI3V3;
float AmpsI5V;
float AmpsI12V;
float AmpsI24V;

float Watt3V3;
float Watt5V;
float Watt12V;
float Watt24V;




void setup() {

  Serial.begin(9600);
  analogReference(INTERNAL1V1);
  lcd1.begin();
  lcd1.backlight();
  lcd2.begin();
  lcd2.backlight();
  lcd3.begin();
  lcd3.backlight();
  lcd4.begin();
  lcd4.backlight();
  lcd5.begin();
  lcd5.backlight();



}


void messung_Vcc() {

  ADC_countVcc = 0;
  for (int i = 0; i < averages; i++)
    ADC_countVcc += analogRead(analogIn_Vcc);
  voltageVcc = (R1 + R0) / R0 * U_ref * ADC_countVcc / 1023 / averages;

}

void messung_5V() {

  ADC_countU5V = 0;
  for (int i = 0; i < averages; i++)
    ADC_countU5V += analogRead(analogIn_U5V);
  voltageU5V = (R1 + R0) / R0 * U_ref * ADC_countU5V / 1023 / averages;

  ADC_countI5V = 0;
  for (int i = 0; i < averages; i++)
    ADC_countI5V += analogRead(analogIn_I5V);
  voltageI5V = (R1 + R0) / R0 * U_ref * ADC_countI5V / 1023 / averages;
  ACSoffset = voltageVcc * 0.5;
  AmpsI5V = (voltageI5V - ACSoffset) / 0.066;

  Watt5V = voltageU5V * AmpsI5V;

}

void messung_3V3() {

  ADC_countU3V3 = 0;
  for (int i = 0; i < averages; i++)
    ADC_countU3V3 += analogRead(analogIn_U3V3);
  voltageU3V3 = (R1 + R0) / R0 * U_ref * ADC_countU3V3 / 1023 / averages;

  ADC_countI3V3 = 0;
  for (int i = 0; i < averages; i++)
    ADC_countI3V3 += analogRead(analogIn_I3V3);
  voltageI3V3 = (R1 + R0) / R0 * U_ref * ADC_countI3V3 / 1023 / averages;
  ACSoffset = voltageVcc * 0.5;
  AmpsI3V3 = (voltageI3V3 - ACSoffset) / 0.066;

  Watt3V3 = voltageU3V3 * AmpsI3V3;

}

void messung_12V() {

  ADC_countU12V = 0;
  for (int i = 0; i < averages; i++)
    ADC_countU12V += analogRead(analogIn_U12V);
  voltageU12V = (R2 + R0) / R0 * U_ref * ADC_countU12V / 1023 / averages;

  ADC_countI12V = 0;
  for (int i = 0; i < averages; i++)
    ADC_countI12V += analogRead(analogIn_I12V);
  voltageI12V = (R1 + R0) / R0 * U_ref * ADC_countI12V / 1023 / averages;
  ACSoffset = voltageVcc * 0.5;
  AmpsI12V = (voltageI12V - ACSoffset) / 0.066;

  Watt12V = voltageU12V * AmpsI12V;

}

void messung_24V() {

  ADC_countU24V = 0;
  for (int i = 0; i < averages; i++)
    ADC_countU24V += analogRead(analogIn_U24V);
  voltageU24V = (R3 + R0) / R0 * U_ref * ADC_countU12V / 1023 / averages;

  ADC_countI24V = 0;
  for (int i = 0; i < averages; i++)
    ADC_countI24V += analogRead(analogIn_I24V);
  voltageI24V = (R1 + R0) / R0 * U_ref * ADC_countI24V / 1023 / averages;
  ACSoffset = voltageVcc * 0.5;
  AmpsI24V = (voltageI24V - ACSoffset) / 0.066;

  Watt24V = voltageU24V * AmpsI24V;

}

void loop() {

  

  messung_5V();
  messung_Vcc();
  messung_3V3();
  messung_12V();
  messung_24V();



  lcd1.setCursor(0, 0);
  lcd1.print("U=");
  lcd1.print(voltageU5V, 1);
  lcd1.print(" V");
  lcd1.setCursor(0, 1);
  lcd1.print("I=");
  lcd1.print(AmpsI5V, 2);
  lcd1.print(" A");
  lcd1.setCursor(9, 1);
  lcd1.print("P=");
  lcd1.print(Watt5V, 1);
  lcd1.print(" W");

  delay(1000);
}

[/code]

Sketch 2 (PWM Steuerung)

[code]
#include <LiquidCrystal_I2C.h>


LiquidCrystal_I2C lcd5(0x27, 16, 2); // PWM

#include <RotaryEncoder.h>

#define ROTARYSTEPS 2
#define ROTARYMIN 0
#define ROTARYMAX 100
// Setup a RoraryEncoder for pins A11 and A12:

RotaryEncoder encoder(A11, A12);
// Last known rotary position.

int lastPos = -1;

void setup()
{
  lcd5.begin();
  Serial.begin(9600);
  Serial.println("LimitedRotator example for the RotaryEncoder library.");

  encoder.setPosition(0 / ROTARYSTEPS); // start with the value of 0.



} // setup()
int PWM_Pin = 3;
int PWM = 0;


// Read the current position of the encoder and print out when changed.
void loop()
{
  encoder.tick();

  // get the current physical position and calc the logical position
  int newPos = encoder.getPosition() * ROTARYSTEPS;

  analogWrite(PWM_Pin, PWM);

  if (newPos < ROTARYMIN) {
    encoder.setPosition(ROTARYMIN / ROTARYSTEPS);
    newPos = ROTARYMIN;

  } else if (newPos > ROTARYMAX) {
    encoder.setPosition(ROTARYMAX / ROTARYSTEPS);
    newPos = ROTARYMAX;
  } // if

  if (lastPos != newPos) {
    Serial.print(newPos);
    Serial.println();
    lastPos = newPos;
  } // if

  PWM = map(newPos, 0, 100, 0, 255);

  lcd5.setCursor(0, 0);
  lcd5.print(newPos);
  lcd5.println(" Prozent");
} // loop ()

// The End

[/code]

Hänge Dir in die einzelnen Bestandteile serielle Ausgaben rein, um zu sehen wo Dein zusammenkopierter Sketch lang läuft.

Gruß Tommy

Verstehe ich dich richtig, alle Werte im Seriellen Monitor anzeigen lassen um dann Verzögerungen festzustellen?

Nicht in erster Linie um Verzögerungen zu finden, sondern um den tatsächlichen Ablauf des Programms zu verstehen.

Gruß Tommy

Probier ich morgen mal aus

Habe ich Tomaten auf den Augen, oder ist der zusammengeführte Sketch wirklich nicht da?

Ich tippe mal:

die Encoder Library arbeitet mit Pinchange Interrupts und die verwendeten Pins des Megas unterstützen das nicht.

Hallo,

wozu bildest du die Mittelwerte in einer relativ schnellen Schleife, da ließt Du 25 Werte ein, die sicher fast alle gleich sind und bildest den Mittelwert. Wenn Du ein Brummen (50Hz) mitteln willst must du Messwerte über 300-500ms aufnehmen und die mitteln.

Pack doch das Werte einlesen in eine Schleife (loop) und messe alle 50-100ms mit millis() . Dann würde ich auch mit einem gleitenden Mittelwert arbeiten (PT1 Verzögerung) der wird ständig aktualisiert und ist ständig gültig. Dann kann das Timing dür das einlesen der Messwerte eigendlich kein Problem mehr sein.

Heinz

Hallo zusammen,

Whandall:
Habe ich Tomaten auf den Augen, oder ist der zusammengeführte Sketch wirklich nicht da?

Also bei mir wird im 1. Post der zusammengeführte Sketch angezeigt.

Whandall:
Ich tippe mal:

die Encoder Library arbeitet mit Pinchange Interrupts und die verwendeten Pins des Megas unterstützen das nicht.

Das glaube ich nicht weil die PWM Steuerung funktioniert wenn ich den Sketch 2 alleine laufen lasse ohne Änderung an der Hardware

Rentner:
Hallo,

wozu bildest du die Mittelwerte in einer relativ schnellen Schleife, da ließt Du 25 Werte ein, die sicher fast alle gleich sind und bildest den Mittelwert. Wenn Du ein Brummen (50Hz) mitteln willst must du Messwerte über 300-500ms aufnehmen und die mitteln.

Pack doch das Werte einlesen in eine Schleife (loop) und messe alle 50-100ms mit millis() . Dann würde ich auch mit einem gleitenden Mittelwert arbeiten (PT1 Verzögerung) der wird ständig aktualisiert und ist ständig gültig. Dann kann das Timing dür das einlesen der Messwerte eigendlich kein Problem mehr sein.

Heinz

Durch die Mittelung soll die Messpräzision erhöht werden. Ich muss leider zugeben das der Sketch nicht von mir ist sondern von ELV, ich hab ihn nur angepasst. Ich bin halt leider noch blutiger Anfänger und kann auch mit Begriffen wie PT1 verzögerung wenig anfangen.

Aber du hast recht, große Schwankungen der Werte sind nicht zu erwarten. Also könnte ich auch auf die Mittelung verzichten.

Wenn du den Encoder nur einmal pro Sekunde ausliest, wie soll das funktionieren?

  encoder.tick();

  delay(1000);

Den gedanken hatte ich auch schon, nur wenn ich das delay entferne ändert sich leider auch nichts außer das die Displayanzeigen unruhig werden

BWD.

Da wo ein delay funktionierte wirst du wohl nicht-blockierend arbeiten müssen,
einfaches Löschen von delay hilft da nicht, mit der dauernden Ausgabe verzögerst du das Auslesen
immer noch zu stark, außerdem flackert das Display.

Das Benutzen von delay verhindert in der Regel ein Zusammenführen von Sketches,
das ist dir aber nicht wirklich neu, oder?

Whandall:
Das Benutzen von delay verhindert in der Regel ein Zusammenführen von Sketches,
das ist dir aber nicht wirklich neu, oder?

:frowning: Doch, leider ist mir das neu

Alternative zu delay? millis?

Ja. das Prinzip BWD. Blink Without Delay oder Nachtwächtererklärung.

Millionenmal durchgekaut, ich schätze mal 5-10% aller Threads haben das Problem zum Thema.

Das ein delay das Programm komplett anhält ist mir schon bewusst, ich wusste nur nicht das ein delay das zusammenführen von 2 Sketches verhindert.

Danke für den Tipp, ich versuche das mal zu ändern

Beim Kopf-In-Den-Sand-Stecken passiert halt nichts,
d.h. alles was öfter aufgerufen werden muss, wie z.B. ein Encoder, bleibt da auf der Strecke.

Ja, Interrupts könnten dies Problem lösen, deine Encoder Library scheint aber mit Polling zu arbeiten.

Nicht blockierende Sketches lassen sich normalerweise einfach zusammenführen.

@ Whandall:

Du hattest recht! Delay raus, millis rein und es funktioniert.

Jetzt im nachhinein eigentlich ganz logisch, hätte ich wirklich selbst drauf kommen können.

Danke für eure Hilfe!

Gut.

Ich hoffe dass damit delay() auf deine schwarze Liste kommt,
jedenfalls soweit es um wiederverwendbaren Kode geht. :wink: