PWM Wert einlesen - nur wie?

Hallo,

ich lese mit digitalRead und analogRead die Werte/Zustände von vielen Pins ein. Aber wie lese ich die Werte von den genutzten PWM Pins wieder ein? Das ist ja eigentlich weder rein digital in Form von 0 oder 1, noch analog. analogRead liest nur die analogen Eingänge A0 bis A7 ein (Mega2560).

Mir fällt jetzt nur ein nicht ganz so schöner Weg ein. Die ausgegeben PWM Werte direkt nach Benutzung, also deren Ausgabe, weiterzuverarbeiten wie gewünscht.

Ich hoffe jedoch es gibt noch eine Möglichkeit sie später mit einem normalen Befehl einlesen zu können?

Der Grund ist, ich gebe alle eingelesenen Zustände über die RS232 an Processing aus. Mit den reinen digitalen und analogen Pins klappt das schon soweit.

Die Werte von dem PWM Ausgängen auszulesen macht doch keinen Sinn. Dein Programm sollte eigentlich wissen, was für Werte er wegschickt.

PWM ist mM nach ein digitaler Wert. Es werden halt je nach Tastgrad entsprechende lange Pausen eingesetzt.

Genau, so von alleine PWMt da nix. Also brauchst Du auch nix messen. Oder wir verstehen Dich nicht richtig.

Es macht keinen Sinn einen PWm Wert vom Pin wieder einzulesen. Es ist besser mit der Variablen zu arbeiten. Man kann den PWM-Wert einlesen mit pulseIn() zuerst den H-Teil und denn den L-Teil. pulseIn() blockiert aber wie Delay den Kontroller. Du solltest auch den timout auf einen Wert setzen der etwas über der Periode des PWM-Signals ist.

Beim Arduino MEGA sind nicht nur die Pins A0 bis A7 Analoge eingenge sondern auch die Pins A8 bis A15. Das gleiche gilt für die PWM-Pins : PWM: 2 to 13 and 44 to 46. Provide 8-bit PWM output with the analogWrite() function. Grüße Uwe

Hallo,

ich bin gerade dabei mir eine Art grafische Übersicht in Processing zubauen. Mit Hilfe eines Arduino Buches von Erik Bartmann. Damit sendet der Arduino permanent seine eingelesenen Pins über die serielle nach außen. Das klappt mit digitalen und analogen Pins wunderbar. Ich muß das nur noch für meinen Mega2560 erweitern, dass ist nicht das Problem.

Jetzt wollte ich in die reine Auslese Lopp noch ein kleines Programm einbauen womit ich 3 LEDs per PWM mit einem Poti hin und her schiebe. Mit auf und ableuchten. Das funktioniert ebenfalls alleine. Eine Spielerei damit ich in Processing Änderungen sehe. Den sich änderten Potiwert A0 sehe ich in einem Scrollbalken.

Jetzt wollte ich nicht immer mitten im Programmcode die PWM Variabeln über die Serielle schicken. Würde irgendwann zu unübersichtlich und dachte man kann sie später in dem eh vorhandenen "Ausleseblock" ebenfalls normal wieder abfragen und ausgegeben. Ein gesetztes digitalWrite kann man ja auch mit digitalRead wieder auslesen, irgendwann ... Wie ich nun mitbekommen habe geht das mit PWM nicht. Weil das durch eine "versteckte" Funktion eben getaktet wird. Wie PWM funktioniert und was das ist weis ich.

Also hilft nur Zwischenspeichern oder direkt ausgeben um den Zustand später sehen zu können. Scrollbalken 0 ... 255.

versteckt, NEIN. Uwe hat es bereits angedeutet wie es geht ;) Es ist aber keinesfalls empfehlenswert. Setzt hier mal deinen Sketch von der Arduino IDE rein. Wenn du ohne Delays auskommt, was zu empfehlen ist, ändert sich der PWM Wert doch vermutlich nur einmal pro loop. Einfach den PWM Wert in einer Variable abspeichern, auf die deine Ausgabe zugreifen kann, bzw. als Funktionsparameter übergeben.

Lieber ein paar Variablen mehr, als jedes mal den PWM oder die Digitalen Inputs auslesen!

Hallo,

ich habe das von Uwe schon verstanden. Nur dauert vermutlich die Aktion mit pulsein viel zu lange und würde nur alles unnötig verzögern. Ich dachte man könnte das einfach so auslesen wie digitalRead. Da es nicht so geht, nutze ich jetzt Variablen zum Zwischenspeichern.

Mit der versteckten PWM Funktion meinte ich, dass es eine von den Arduino Machern programmierte Funktion ist. Der analoge PWM Befehl kommt in der Atmega Welt original so nicht vor. Man müßte sich das erst selbst bauen, was wie gesagt die Arduino IDE Entwickler schon gemacht haben. Deswegen versteckt in " ".

der Arduino Programmcode …
Den Processing Sketch kann ich leider nicht posten, hat mehr wie 9500 Zeichen.

// Arduino Mega 2560

int LED_R = 8;   // an Pin 8
int LED_G = 9;   // an Pin 9
int LED_B = 10;  // an Pin 10
int analogPin = 0;     // Poti am analog pin A0 
int val = 0;           // Potiwert speichern in val
int val_mapped = 0;    // Potiwert für PWM umgewandelt

void setup(){
  Serial.begin(9600); // Übertragungsrate

  // LED Pins auf Ausgang setzen
  pinMode(LED_R, OUTPUT);  
  pinMode(LED_G, OUTPUT);    
  pinMode(LED_B, OUTPUT);   
  
  // kurzer LED Funktionstest
  digitalWrite(LED_R, HIGH);    // Rot EIN
  delay(300);                
  digitalWrite(LED_G, HIGH);    // Grün ein
  delay(300);                
  digitalWrite(LED_B, HIGH);    // Blau ein
  delay(300);    
  digitalWrite(LED_R, LOW);   // ROT aus
  digitalWrite(LED_G, LOW);   // Grün aus
  digitalWrite(LED_B, LOW);   // Blau aus
  // Ende des LED Funktionstest
  
  // alle digitalen Eingänge mit PullUp aktivieren  
  for(int i = 46; i <= 53; i++) {  // Pin 46 bis 53
     pinMode(i, INPUT);            // setzt pin als Eingang
     digitalWrite(i, HIGH);        // aktiviert den PullUp Widerstand 
    }

}
void loop(){
  
    val = analogRead(analogPin);         // reads the value of the potentiometer (value between 0 and 1023)
    
  // *** LED ROT **************************************  
  if (val <= 170) {
    // digitalWrite(LED_G, 0);
    val_mapped = map(val, 0, 170, 0, 255);
    analogWrite(LED_R, val_mapped);
    }
   
  if (val >= 171 && val <= 340) {
    digitalWrite(LED_G, 0);
    val_mapped = map(val, 171, 340, 255, 0);
    analogWrite(LED_R, val_mapped);
    }

  // *** LED GRÜN **************************************    
  if (val >= 341 && val <= 513) {
    digitalWrite(LED_R, 0);
    // digitalWrite(LED_B, 0);
    val_mapped = map(val, 341, 513, 0, 255);
    analogWrite(LED_G, val_mapped);
    }
  
  if (val >= 514 && val <= 683) {
    digitalWrite(LED_B, 0);
    val_mapped = map(val, 514, 683, 255, 0);
    analogWrite(LED_G, val_mapped);
    }
 
  // *** LED BLAU **************************************      
  if (val >= 684 && val <= 853) {
    digitalWrite(LED_G, 0);
    val_mapped = map(val, 684, 853, 0, 255);
    analogWrite(LED_B, val_mapped);
    }
  
   if (val >= 854) {
    val_mapped = map(val, 854, 1023, 255, 0);
    analogWrite(LED_B, val_mapped);
    }

  // für Processing
  // Sende analoge Werte
  for(int i = 0; i <= 15; i++)     // Pin 0 bis 15
    Serial.println(normalize("A", i, analogRead(i)));
  // Sende digitale Werte
  for(int i = 46; i <= 53; i++)    // Pin 46 bis 53
    Serial.println(normalize("D", i, digitalRead(i)));
    
} // Loop Ende

// Klassen
String normalize(String t, int pin, int value){
  String pinString = String(pin);
  String valueString = String(value);
  if(pin < 10)
    pinString = "0" + String(pin); // Wenn einstellig, dann führende Null anfügen
  int count = 4 - valueString.length(); 
  for(int i = 0; i < count; i++)
    valueString = String("0") + valueString; // Führende Nullen 
                                   // anfügen
  String r = String("S") + String(t) + String(pinString) + 
                   String(valueString) + String("E");
  return r; // Normalisierte Zeichenkette wird zurückgeliefert
}

hi,

natürlich kannst Du diese werte auch wieder auslesen. alles, was man dazu braucht, steht in, wenn ich mich jetzt recht erinnere, drei registern (ein wert sagt zb, welcher der 4 PWM-modi benutzt wird. also viel spaß beim viel nachlesen). den sinn dahinter sehe ich nicht, weil Du den PWM-wert ja selbst setzt, und wenn Du die variable nicht vernichtest, ist das keine umgehung, sondern der beste weg. falls Du doch register lesen willst: es geht.

gruß stefan

Hallo,

okay, mit Registern möchte ich mich noch nicht so tief befassen wenn es nicht unbedingt sein muß. Ich speicher die Werte jetzt zwischen und gebe sie am Ende mit allen anderen aus.

Kann ich hier auch eine Frage zu Processing stellen? Ich habe nämlich ein Problem mit der Darstellung der analogen Scrollbalken nebeneinander. Untereinander wird alles richtig ins Fenster gemalt. Setze ich weitere daneben, wird etwas Müll angezeigt. Als wenn die Zeichenfunktion draw ohne Rücksicht die Zeile komplett überschreibt.
Der Processing Sketch liegt im Dateianhang. Wenn man die auskommentierten 4 IF Abfragen bei “Ist Datentyp PWM Analog” wieder hinzunimmt, werden die 3 Balken dargestellt, aber leider etwas fehlerhaft im Detail. Platziert man sie weiter unten, soweit man Platz hat, funktioniert alles.

Wegen Copyright noch eine Anmerkung. Die Basis vom Code stammt aus Erik Bartmann seinen Arduino Buch. Nicht das ich mit Erik Ärger bekommen.

zum Arduino Code testen einfach ein Poti an A0 anschließen und 3 LEDs an Pin 8 bis 10, dann Poti langsam drehen …

// Arduino Mega 2560

int LED_R = 8;   // an Pin 8
int LED_G = 9;   // an Pin 9
int LED_B = 10;  // an Pin 10
int analogPin = 0;     // Poti am analog pin A0 
int val = 0;           // Potiwert speichern in val
int val_mapped = 0;    // Potiwert für PWM umgewandelt
int val_PWMwert_R = 0; // Zwischenspeicher für RS232 Ausgabe
int val_PWMwert_G = 0; // Zwischenspeicher für RS232 Ausgabe
int val_PWMwert_B = 0; // Zwischenspeicher für RS232 Ausgabe

void setup(){
  Serial.begin(9600); // Übertragungsrate

  // LED Pins auf Ausgang setzen
  pinMode(LED_R, OUTPUT);  
  pinMode(LED_G, OUTPUT);    
  pinMode(LED_B, OUTPUT);   
  
  // kurzer LED Funktionstest
  digitalWrite(LED_R, HIGH);    // Rot EIN
  delay(300);                
  digitalWrite(LED_G, HIGH);    // Grün ein
  delay(300);                
  digitalWrite(LED_B, HIGH);    // Blau ein
  delay(300);    
  digitalWrite(LED_R, LOW);   // ROT aus
  digitalWrite(LED_G, LOW);   // Grün aus
  digitalWrite(LED_B, LOW);   // Blau aus
  // Ende des LED Funktionstest
  
  // alle digitalen Eingänge mit PullUp aktivieren  
  for(int i = 46; i <= 53; i++) {  // Pin 46 bis 53
     pinMode(i, INPUT);            // setzt pin als Eingang
     digitalWrite(i, HIGH);        // aktiviert den PullUp Widerstand 
    }

}
void loop(){
  
    val = analogRead(analogPin);         // reads the value of the potentiometer (value between 0 and 1023)
    
  // *** LED ROT **************************************  
  if (val <= 170) {
    val_mapped = map(val, 0, 170, 0, 255);
    analogWrite(LED_R, val_mapped);
    val_PWMwert_R = val_mapped;      // Zwischenspeicher für RS232 Ausgabe
    }
   
  if (val >= 171 && val <= 340) {
    digitalWrite(LED_G, 0);          // vorhergehende LED sicher ausschalten
    val_PWMwert_G = 0;               // Zwischenspeicher löschen sonst Anzeige verfälscht
    val_mapped = map(val, 171, 340, 255, 0);
    analogWrite(LED_R, val_mapped);
    val_PWMwert_R = val_mapped;      // Zwischenspeicher für RS232 Ausgabe
    }
  
  // *** LED GRÜN **************************************    
  if (val >= 341 && val <= 513) {
    digitalWrite(LED_R, 0);          // vorhergehende LED sicher ausschalten
    val_PWMwert_R = 0;               // Zwischenspeicher löschen sonst Anzeige verfälscht
    val_mapped = map(val, 341, 513, 0, 255);
    analogWrite(LED_G, val_mapped);
    val_PWMwert_G = val_mapped;      // Zwischenspeicher für RS232 Ausgabe
    }
  
  if (val >= 514 && val <= 683) {
    digitalWrite(LED_B, 0);          // vorhergehende LED sicher ausschalten
    val_PWMwert_B = 0;               // Zwischenspeicher löschen sonst Anzeige verfälscht    
    val_mapped = map(val, 514, 683, 255, 0);
    analogWrite(LED_G, val_mapped);
    val_PWMwert_G = val_mapped;      // Zwischenspeicher für RS232 Ausgabe
    }
  
  // *** LED BLAU **************************************      
  if (val >= 684 && val <= 853) {
    digitalWrite(LED_G, 0);          // vorhergehende LED sicher ausschalten
    val_PWMwert_G = 0;               // Zwischenspeicher löschen sonst Anzeige verfälscht    
    val_mapped = map(val, 684, 853, 0, 255);
    analogWrite(LED_B, val_mapped);
    val_PWMwert_B = val_mapped;      // Zwischenspeicher für RS232 Ausgabe
    }
  
   if (val >= 854) {
    val_mapped = map(val, 854, 1023, 255, 0);
    analogWrite(LED_B, val_mapped);
    val_PWMwert_B = val_mapped;      // Zwischenspeicher für RS232 Ausgabe
    }

  // für Processing
  // sende analoge Werte
  for(int i = 0; i <= 15; i++)     // Pin 0 bis 15
    Serial.println(normalize("A", i, analogRead(i)));
  Serial.println(normalize("P", LED_R, val_PWMwert_R));
  Serial.println(normalize("P", LED_G, val_PWMwert_G));
  Serial.println(normalize("P", LED_B, val_PWMwert_B));
  // Sende digitale Werte
  for(int i = 46; i <= 53; i++)    // Pin 46 bis 53
    Serial.println(normalize("D", i, digitalRead(i)));
    
} // Loop Ende

// Klassen
String normalize(String t, int pin, int value){
  String pinString = String(pin);
  String valueString = String(value);
  if(pin < 10)
    pinString = "0" + String(pin); // Wenn einstellig, dann führende Null anfügen
  int count = 4 - valueString.length(); 
  for(int i = 0; i < count; i++)
    valueString = String("0") + valueString; // Führende Nullen 
                                   // anfügen
  String r = String("S") + String(t) + String(pinString) + 
                   String(valueString) + String("E");
  return r; // Normalisierte Zeichenkette wird zurückgeliefert
}

LED_Poti_AnalogDigitalTalker.zip (2.53 KB)