Volt und Milivolt mit dem Ardurino Uno R3 ermitteln und weiter verarbeiten

Hallo in die Gemeinschaft, Ich bin der NEUE.
Ja, ganz neu im Feld der Mikrocontroller, jedoch etwas erfahren im Bereich der Elektronik.
Bin Lizenzierter Funkamateur und der Zufall brachte mir den Arduino Uno R3 ins Haus. Das weckt natürlich Begehrlichkeiten damit herum zuspielen. Vom Programmieren an sich habe ich nur wenig Kenntnisse, eben was man so für die Bash benötigt aber auch nichts was in die Tiefe geht.

Ich finde es eine Gute Idee mit dem Uno ein Voltmeter aufzubauen um so Zwei Spannungen gleichzeitig auf einem Display 20 x 4 auszugeben.
Allerdings wäre es hilfreich die 2.Anzeige als Millivoltmeter auszulegen.
Also um meinen Wunsch zu verdeutlichen:

U_0=5V max
############## Bargraph_0
############## Bargraph_1
U_1=0.099 max

Ich habe ein wenig Code dazu im Netz gefunden, welchen ich nach meinem Gutdünken abgeändert habe und nun möchte ich diesen erweitern, so das sich das obere Bild ergeben kann.

Hier der Code:

[code]
#include <LiquidCrystal.h>

#include <LcdBarGraph.h>

const int rs = 7, en = 8, d4 = 9, d5 = 10, d6 = 11, d7 = 12;

LiquidCrystal lcd(rs, en, d4, d5, d6, d7);


byte lcdNumCols = 20;               //Anzahl der Zeichen_Blöcke
byte lcdLine = 4;                   //Anzahl der Reihen die 20 Blöcke enthalten
byte sensorPin_0 = A0;              //Pin der Spannung liefert

                                    
LcdBarGraph lbg(&lcd, 20, 0, 1);    //erzeugt die Bar 20 Zeichen lang (100 Teile) Stelle 0 Zeile 1

        
void setup(){
                                    
  lcd.begin(20,4);                
  lcd.clear();                    //löscht alle Zeichen
  lcd.setCursor (6,0);            //Setzt die Position des folgenden Text
  lcd.print("------");            //TEXT
  lcd.setCursor (2,2);            //Setzt die Position des folgenden Text
  lcd.print("Voltage Bargraph"); //TEXT
   
                                  
  delay(5000);                    // Anzeigendauer Text oben
  lcd.clear();                    // Vermeidet Artefakte in der folgenden Anzeige
}

void loop()
{
  //  Voltmeter an pin A0         // Min V=0.00 Max V=5,1 Z-Diode nach Masse

  int inpuValue = analogRead(A0);                 // lese pin A0
                                          
  lbg.drawValue( inpuValue, 1024);                // Zeichnet den Bargraph mit <LcdBarGraph>
                                                
  float voltage0 = inpuValue * (5.0 / 1023.0);   // setzt die auflösung auf 10bit
  lcd.setCursor (0,0);                           //
  lcd.print("Volt:");                            //
  lcd.setCursor (8,0);                           // Siehe oben beim 
  lcd.print(voltage0);                           //
  lcd.setCursor (12,0);                          //
  lcd.print("V");                                //
 
  delay(100);
}



[/code]

Habe ich die Anweisungen alle richtig zusammengesucht?
Das Angeschlossene Display ist schon Antik, ist ein Truly aus 1998.

Ich bedanke mich schon im voraus für eure Antworten

Wenn Du für U_1 eine wenigstens geringe Auflösung haben willst, musst Du mit der Referenzspannung von 1,1V arbeiten (1,1V --> 1023 Einheiten). Wenn Dir das zu grob ist, wird das direkte Messen dieser Spannung nichts.
Die 5V musst Du dann über einen Spannungsteiler auf 1,1V runter teilen.

Gruß Tommy

Diese Rechnung ist falsch, aus mehreren Gründen:

  1. 10 Bit sind 1024 und nicht 1023 Stufen
  2. Die 5V sind eher 4,7V
  3. Für absolute Messungen verwendet man die interne Referenz, und nicht Vcc.

Zum Ausgleich der Toleranz Abweichung der internen Referenz kann man sehr schön die 2 Punkt Kalibrierung zum Einsatz bringen. (Geradengleichung)

Den Spannungsteiler sollte man getrennt vom 1000 mV Messbereich kalibrieren.
Und wenn sowieso ein Spannungsteiler gebaut wird, warum nicht einen für 10V max?

Hallo,

schau mal hier

Heinz

Die Spannung die von der USB-Schnittstelle kommt ist wenig konstant bzw sicher.
Die Spannung kann zwischen erfahrungsgemäß 5,1 und 4,6 V sein. Darum muß die Referenzspannung 5,0V gemessen werden und dementsprechend in den Sketch eingetragen werden. Dies verhindert aber nicht daß diese Spannung an einem anderen PC, Netzteil oder USB-Buchse verschieden sein könnteund damit die Messung falsch ist.

Abhilfe könnte wie bereits vorgeschlagen die interne Referenzspannung der Controller sein.
Der ATmega168, - 328 hat eine interne 1,1V Referenz
der ATmega1280 - 2560 hat 1,1 und 2,56V
der ATmega32U4 hat 2,56V
Andere Controller weiß ich nicht auswendig.
Diese Spannungen sind nicht ganz genau (10%) aber langzeitstabiel. Für eine genaue Spannugsmessung sollte diese am AREF Pin gemessen und in den Sketch eingetragen werden.
Alternativ kann an AREF-Pin eine Referenzspannung eingespeist werden. Dazu muß im Sketch die Referenzspannungsquelle auf EXTERN gestellt werden und eine Referenzspannungsquelle angeschlossen werden.
Die Referenzspannung sollte nicht unter 1V betragen.

Grüße Uwe

Herzlichen Dank an die Autoren für die detaillierten Hinweise. Die Bandbreite der angesprochenen Themen zeigt, was ich nicht beschrieben habe.
Es fällt mir immer schwerer meine Analogen Messgeräte abzulesen. Eine Anzeige zu haben die ich auf doppelte Armlänge auch ohne Brille erkennen kann, wäre die Lösung.

Im Detail geht es darum die Spannungen darzustellen, welche ein Richtkoppler zur Verfügung stellt.
Mit Hilfe so einer Vorrichtung werden auf zwei Drehspurinstrumenten die Vorlaufende und die Reflektierte Sendeleistung, gleichzeitig auf einem gemeinsamen Zifferblatt dargestellt. Das nennt sich Kreuzzeiger. Mit diesem Begriff kann sich der Interessierte bei Google informieren.

Also auf die Genauigkeit des Messwertes kommt es nicht so an. Auf das Verhältnis von U_0 zu U_1 dagegen schon. Die Bedingung " U_0 max = U_1 im Bereich von +- 5 mV" würde was brauchbares auf dem Display darstellen.

Aber bevor ich mich in unverständlicher Schreiberei verliere.

Hätte nicht jemand einen Link zu einem sehr sehr simpelen Audio µV Meter? Dessen Code meinen Anforderungen in etwa ähnlich wäre? So könnte ich eben mal anklemmen und ausprobieren wie sich der Testaufbau unter realen Bedingungen verhalten würde.

Danke im voraus .

Als wenn ein Kreuzzeiger Instrument hier keinem bekannt wäre....
Aber für blöd erklären ist immer einfacher, als vorher schon damit rauszurücken, was du erreichen willst.
z.B. ein Stehwellenmessgerät bauen.
Zwecks Antennenanpassung?

Tipp:
Es gibt durchaus Arduinos mit differenziellen ADCs und einstellbarem Gain.
z.B. der Mega

Da Du Wechselspannung messen willst mußt Du diese zuerst gleichrichten. Danach kannst Du die Spannung verstärken. Beides kannst Du mittels Operationsverstärker machen.

Andererseits gibt es AD/Wandler als ICs. Man kann einen AD-Wandler mit mehr Auflösung nehmen und diesen an den Arduino anschließen.

Grüße Uwe

Nun ich habe gesucht und doch noch ein brauchbares Beispiel gefunden, das meinen Bedarf decken kann.
Jedoch ist schon in der Uhrschrift ein Fehler enthalten.
Der Lautet so:
warning: comparison between signed and unsigned integer expressions [-Wsign-compare] if(millis() < lastT)

Auf was deutet diese Meldung den hin? Die IDE bricht den Vorgang jedoch nicht ab und das Programm scheint fehlerfrei zu laufen.
Ich hatte zuerst den Verdacht, da ich das Display von 16x2 auf 20x4 abgeändert habe, wäre der Auslöser gewesen. Dabei habe ich wohl nicht so viel falsch gemacht.

Der Urheber stellt diesen Sketch nicht Ausdrücklich der Allgemeinheit zur Verfügung, daher füge ich den YouTube-Link hier ein. Die Quelle ist dort verlinkt.

Ich wage es zunächst nicht diesen Sketch hier so einfach zu Posten.

Danke für Eure Mühe und Aufmerksamkeit

? was du meinen ?
Warnung: Vergleich zwischen vorzeichenbehafteten und vorzeichenlosen Integer-Ausdrücken [-Wsign-compare]
Sogar die Zeile und Datei wird dir zur Meldung geliefert....

Was millis() liefert, kann ich nachsehen, wenn ich's nicht weiß. Offensichtlich ist dein geheimes lastT Mist.
Das ganze ist auch nur eine Warnung, die erst weh tut, wenn lastT negativ wird.

Eine Warnung ist eine Warnung, kein Fehler. Aus einer warnung könnte aber ein Fehler werden.

Der Compiler/Linker gibt Warnungen und Fehler aus bei Fehlern wird die Kompilierung abgebrochen. Bei Warnungen wird kompiliert.

Grüße Uwe

Hallo in die Runde.

Ich hatte nun die Gelegenheit den Code und den UNO auf seine HF-festigkeit zu testen. So in meiner offenen Bauweise scheint sich das alles in Grenzen zu halten. Ebenso hatte ich die Befürchtung, das ich das unvermeidliche Rauschen am "Reflecktet" Sensor in Engen Grenzen halten lässt. 0 Volt feststellen ist ja immer so eine Sache, wenn HF im Spiel ist. Ich meine Festgestellt zu haben, das es nicht schädlich ist, die nicht benötigten Analogen Eingänge mit 500K auf Masse zu legen. So können diese kaum noch Unfug anstellen. Definiertes Potenzial. Das Tiefpass-Filter direkt an A4 A5 mit 200µH und 0,01µF stellt eine hinreichende Dämpfung der HF bereit.
Scheint bis jetzt hinreichend "Weich" zu laufen.

Allerdings ist es mir nicht möglich die folgenden Code Zeilen zu entschlüsseln.

  1. lcd.write(row ? 'F' : 'R');
    Was ist der Sinn und der Zweck?

  2. int anL = map(sqrt(analogRead(IN_LEFT)*19), 0, 128, 0, 100);
    Ebenso hier, benötige ich ein etwas Nachhilfe.

Den Sketch so weit ich den Selben verstanden habe, ist nur unvollständig kommentiert.
Für mich und jeden Anderen, wäre es wohl sehr hilfreich wenn die Funktionen genauer beschrieben werden könnten.

Ich bitte hiermit darum den Code zu überprüfen und dabei den einen oder anderen Kommentar zu ergänzen.

Die Vorangegangene Warnmeldung konnte ich durch ändern von
long lastT = 0; in unsigned long lastT = 0;
Beheben.

Besten Dank im Voraus

[code]
#include <LiquidCrystal.h>
 
#define IN_LEFT    A4  // analog input for left channel
#define IN_RIGHT   A5  // analog input for right channel
 
#define T_REFRESH    25                   // msec bar refresh rate
#define T_PEAKHOLD   (50 * T_REFRESH)     // msec peak hold time before return
 
LiquidCrystal lcd(7,    // RS
                  8,    // E
                  9,    // DB4
                  10,   // DB5
                  11,   // DB6
                  12    // DB7
                  );
 
byte  fill[6] = {0x20, 0x00, 0x01, 0x02, 0x03, 0xFF};       // character used to fill (0=empty  5=full)
byte  peak[7] = {0x20, 0x00, 0x04, 0x05, 0x06, 0x07, 0x20}; // character used to peak indicator
byte block[8][8]=
{
  {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, // define character for fill the bar
  {0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
  {0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C},
  {0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E},
 
  {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}, // define character for peak level
  {0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04},
  {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02},
  {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
};
 
int lmax[2];    // level max memory
int dly[2];     // delay & speed for peak return

unsigned long lastT = 0;
 
void  bar(int row, int lev) {
 
    lcd.setCursor(0, row);
//   lcd.write(row ? 'F' : 'R');
 
    for(int i = 1; i < 20; i++) {
        int f = constrain(lev-i*5, 0, 5);
        int p = constrain(lmax[row]-i*5, 0, 6);
        if(f)
            lcd.write(fill[f]);
        else
            lcd.write(peak[p]);
    }
 
    if(lev > lmax[row]) {
        lmax[row] = lev;
        dly[row]  = -(T_PEAKHOLD) / T_REFRESH;      // Starting delay value. Negative=peak don’t move
    }
    else {
        if(dly[row] > 0)
            lmax[row] -= dly[row];
 
        if(lmax[row] < 0)
            lmax[row] = 0;
        else
            dly[row]++;
    }
}
 
void  setup() {
 
    byte fillbar[8] = {
    B00000,
    B01000,
    B01100,
    B01010,
    B01001,
    B01010,
    B01100,
    B01000
    };
 
    byte mark[8] = {
    B00000,
    B01010,
    B10001,
    B10101,
    B10001,
    B01010,
    B00000,
    B00000
    };

 
    lcd.begin(20, 4);           //Vorspann beginnt
 
    lcd.createChar(0, fillbar);
    lcd.createChar(1, mark);
 
    lcd.setCursor(2, 3);
    lcd.print("RF PEAK & LEVEL");
    
 
    for(int i = 0; i < 20; i++) {
        lcd.setCursor(i, 1);
        lcd.write((byte)0);
 
        delay(150);
    }                           //Vorspann beendet
 
    lcd.clear();

    lcd.setCursor(0, 0);
    lcd.write("Power  =");    //Nur Text in 0

    lcd.setCursor(0, 3);
    lcd.write("Revers =");    //Nur Text in 3
 
    for(int j = 0; j < 8; j++)
        lcd.createChar(j, block[j]);
        
}
 
void  loop() {
 
    if(millis() < lastT)
        return;
 
    lastT += T_REFRESH;
    
                                  // sqrt to have non linear scale (better was log)
    int anL = map(sqrt(analogRead(IN_LEFT)*19), 0, 128, 0, 100);
    int anR = map(sqrt(analogRead(IN_RIGHT)*19), 0, 128, 0, 100);
     
    bar(1, anL);
    bar(2, anR);
}
[/code]

Das ist der "ternäre Operator".
Die Erklärung dazu findet sich in jedem C und C++ Grundlagenbuch.
Auch Google kennt den Begriff.

Das überlebt den Überlauf nicht schadlos.

Hi @combie , Ich bedanke mich höflich für Deine Unterstützung.

Ich habe so erkannt das ich wohl sehr analog denke. Ob ich den "ternäre Operator" verstanden habe?
Wohl eher nicht.
Und im weiteren scheint sich der Controller in gewissen Zeitabständen zu verrechnen. Das in deinem Link herausstellt. Auf den Rest der Diskussion gehe ich so nicht weiter ein.

Aber so ein Arduino weckt ja bekanntlich Begehrlichkeiten.
Es ist ja schon mal sehr hilfreich eine viel genauere Anzeige zu haben. Stelle mich aber auch vor, das der Controller die Abstimmung meines L-Tuners ganz allein vornehmen könnte.

Man sollte meinen das das Netz voll von Beispielen ist, auf welche weise solche Steller Automaten in Software zu Bewerkstelligen wären. NIX ist !

Ist Dir eine Quelle bekannt, in Welcher solche Aufgaben Diskutiert werden?

Einige Fachbegriffe, in dieser Hinsicht, würden mir schon helfen Zielorientierte Fragen zu stellen.

Besten Dank im voraus

Das ist sicherlich möglich.
Wenn du deine "Stellglieder" mit einem Antrieb versiehst.
Oder (Koax)Relais verwendest.

Und nein, ich wüsste nicht, dass das schon mal jemand gemacht hat.
Aber das heißt ja auch Programmieren!
Was noch nicht gibt, wird gebaut.

Du möchtest also irgendeine Sorte von Optimum finden..
Richtig?

Ha hilfts nix, da wirst du irgendeine Form einer Bewertungsfunktion bauen müssen.
Automatisch an deinen Stellgliedern rum drehen dürfen, und immer schauen, welche Stellung besser ist.
Schlussendlich:
Du wirst dein Intelligenz/Verhalten/Wissen formalisieren dürfen und dieses dann in C++ gießen.

Von Start, bis Optimum gefunden, hat es Ähnlichkeiten mit einem Regler.
z.B ähnlich mit "PID Regler"

Für das Grundgerüst bieten sich "Endliche Automaten" oder "Schrittketten" an

@combie
Hi und herzlichen Dank für Dein Interesse.
Ich habe mich gestern mit einem OM über mein Vorhaben unterhalten. Mit dem Ergebnis das ein
Proportional Integral Differenzial Algorithmus zum Ziel führen könnte.
Folgende Geräteschaft steht zur Verfügung:
Ein L-Tuner, angetrieben mit zwei DC-Motoren, beide mit Getriebe. Besteht aus Dreko und einem Russischen Kugel_Variometer, schweres Messinggetriebe das lange nachläuft.
Beide, Spule und Dreko haben keine mechanische Begrenzungen oder Endschalter. Können sich frei bewegen also 2x 180°.
Mit meiner Hand-Fernsteuerung lässt sich das Variometer nur auf den PUNKT schubsen. Die Mechanik ist also recht Masse-Träge. So ein Regler würde sich ja auf den PUNKT "Einpendeln", idealerweise die Motorspannung über die PWM immer weiter reduzieren bis der PUNKT Stimmt . Der Dreko wird mit einem Modell-Servo Ohne Steuerung angetrieben. Diese benutze ich als Pwm für beide Motoren um diese feinfühlig fern steuern zu können.
Ich fahre die Motoren nach einander, Vor-und Rückwärts, nicht zusammen oder gleichzeitig.
Was ich als Kriterium dabei verwende, habe ich ja schon oben beschrieben, jedoch hier im Detail:
Eine ausgebaute SWR-Messbrücke liefert mir die Rückmeldung nach welcher ich die Kontrollen selbst bediene. 5V als Ref. Sind deutlich zu Grob gewählt.
Die Motoren werden dabei im Wechsel immer wieder geringfügig verstellt, bis sich eine maximale Spannung am "Vorlauf", Maximaler Strom im Antennen-Kabel und 0 Spannung am "Rücklauf"Keine messbare Störspannung ergibt. Diesen PUNKT gibt es in der Schaltung L_TUNER nur EIN mal, hier ist dieses Anpassungsnetzwerk eben Vorteilhaft EINDEUTIG. Den Stellwinkel der Reaktanzen zu wissen oder auszumessen scheint mir überflüssig.
Ach ja, es ist sichergestellt aus meiner Erfahrung, dass auf jeder Frequenz dieser Resonanzpunkt vorhanden und einstellbar ist. Noch zu bemerken wäre, dieser Resonanzpunkt stellt sich auf dem 10Meter-Band Messerscharf, dagegen auf dem 80Meter-Band wie ein sanfter Hügel dar. Hierbei ist der Bargraph eine echte Erleichterung beim fahren der Spule. Das LCD zeigt in Echtzeit an.

Ich hoffe das meine Beschreibung einen Zielführenden Charakter erhalten hat, so das Du dir vorstellen kannst was ich mir ausgedacht habe.
Im Übrigen wird die PID Regelung immer nur mit einem Motor und einem Feedback vorgestellt, was mich zwar begeistert aber nicht darin unterstützt mental zu reorganisieren.

Ich hoffe es könnte Dir eine Freude sein, so ein Projekt im Detail zu Kritisieren. Schließlich habe ich nur rein Analog und Mechanisch beschrieben. Bin eben nur Schlosser, aber auch Funkamateur.

Freue mich von Dir zu lesen. Sollte Dir das ganze aber zu Stressig sein, schreibs einfach und dann ist auch schon gut.

Da mache dir mal keine zu großen Hoffnungen....
µC und ihre Programmierung, Ja, etwas Übung habe ich da schon.
Funktechnik, eher nein, nur Halbwissen.

in #3 versuchte ich schon zu sagen, dass sowieso die interne Referenz zu empfehlen ist.

Das hört sich doch nach einem klassischen endlichen Automaten an.
Abwechselndes Optimum suchen.

Das lässt sich sich doch sicherlich in einem Modell abbilden.

Hallo @combie , mir scheint Du hast ein wenig Interesse an diesem Projekt gefunden.

Mit mir ist es genau umgekehrt, von Programmieren habe ich nicht mal eine Ahnung, vom Funk und Ekeltrick dagegen sehr viel mehr.

Zur Refferenz: Der Uno hat ja eine Eigene, die benutzt werden kann. Die Spannung am Eingang kann ich mit einem Teiler auf jeden Wert der Sinnvoll ist begrenzen oder auch mit einem Buffer deutlich anheben. Je nach dem wie sich das unvermeidliche Rauschen als Störend herausstellen würde.
Wenn der Bargraph keinen Teilstrich(von 100) mehr anzeigt, bringt der Test am Voltmeter noch 100µV .
Das Originalinstrument spricht erst bei 1mV an. Der erste Wert ist von Hand erstaunlich leicht mit Hilfe der LCD-Anzeige einstellbar.

Der Automat(ix)
Analog aufgebaut möchte ich einen Schmitt_trigger mit Variabler Hysterese einsetzen. So machen das Messgeräte welche den Messbereich selbst auswählen. Nur DAS ist eben nicht der Plan.
Den UNO kann sich jeder Schüler kaufen und eine H-Vollbrücke ist für nen 5er zu haben, die einfach am UNO zu befestigen ist.

Bleibt noch das schwere Getriebe zu bändigen.
Also Analog würde ich mit dem einschränken der Hysterese, gleichzeitig die Spannung am Motor verringern, so, bleibt Dieser irgendwann von selber stehen und Brummt dann vor sich hin.
Wähle ich dieses "Fenster" breit genug, der letzte Komparator stellt das Fenster wieder etwas auf, bleibt der Motor abgeschaltet.
Bis hier hin hätte ich 18 Komparatoren und einen Sack voll Widerstände verbaut. Das Lohnt sich in einiger Hinsicht nicht und ist auch nicht "Praktisch" oder gar zum Nachmachen geeignet.

Der UNO könnte ja herkommen und beim Durchkurbeln der Motoren eine Tabelle mit Messwerten angelegen. Wenn die Einschaltdauer bekannt wäre, so könnte rechtzeitig die Drehzahl abgesenkt, gebremst und pünktlich angehalten werden, so sich der zuvor ermittelte Messwert nähert.
Beide Motoren könnten so gesteuert werden. Es ist aber überhaupt nicht bestimmt das mit einem Durchlauf der Ideale Bereich gefunden werden kann. Einige, wohl 6 Wiederholungen sollten aber ausreichend sein um ein Hinreichendes Ziel zu erreichen.
Der Servo hat eine Stellzeit bei 5v von 0.8sek für 180°.
Das Vario ist in der Stellzeit sehr viel träger, 180° mit 5V ca 40 Sekunden. Bei höherer Spannung wird das auch schneller, 28Volt, dreht dann aber noch lange nach. Masse eben.

Also den letzten Absatz muss ich noch mal genauer überdenken, und auf Blödsinn überprüfen.
Aber so, derartig stellt sich der Automat(ix) in meiner Phantasie eben dar.

Die Spinnen eben die Römer, und ich wohl auch.
Also in diesem Sinne, Grüße aus Bielefeld.