Potentiometer in Processing

Hallo,

Ich habe ein Poti an meinem Arduino Duemilanove angeschlossen und lasse die Werte am pc ausgeben. In Arduino funktioniert das auch soweit und die Werte steigen linear an. In Processing jedoch steigen die Werte erst sehr spät, aber dann sehr stark, an. Ich nutze in Processing die Arduino Library.
Ich hoffe ich könnt mir sagen woran das liegt bzw. wie man lineare Werte bekommt.

KloolK

Hat denn niemand eine Idee woran das liegen könnte? :(

Hi, du solltest vielleicht mal den Code posten den du auf dem Arduino laufen lässt, um die Daten an Processing weiterzugeben. Der Processing-Code kann auch nicht schaden.
Ohn zu wissen, was der µC und dein Processing da genau treiben wird dir leider niemand weiterhelfen können :wink:

Okay also auf dem Arduino läuft StandardFirmata 2.1beta7, wobei ich in dem Sketch Firmata.begin() ohne Paramter aufrufe, da sonst gar keine Kommunikation mit dem Ardunio möglich ist.

In Processing habe in folgenden Code:

import cc.arduino.*;
import processing.serial.*;

int ledPin = 13;
int potiPin = 0;
int potiVal = 0;

Arduino arduino;

void setup() {
  arduino = new Arduino(this, Arduino.list()[1]);
  arduino.pinMode(ledPin, Arduino.OUTPUT);
  arduino.pinMode(potiPin, Arduino.INPUT);
}

void draw() {
  potiVal = arduino.analogRead(potiPin);
  println(potiVal);
  if(potiVal >= 512) arduino.digitalWrite(ledPin, Arduino.HIGH);
  else arduino.digitalWrite(ledPin, Arduino.LOW);
  background(204);
  fill(255,0,0);
  ellipse(50,50,floor(potiVal/10),floor(potiVal/10));
}

Alles kompiliert einwandfrei, nur die Werte vom Poti sind nicht linear, bei ca. 80% Drehung fangen die Werte erst an zu steigen. Ohne Procsessing, also nur in Arduino, liefert der Poti gleichmäßig steigende Werte von Anfang an.
Im verwendeten Processing-Sketch funktioniert die LED auch einwandfrei, also kann es eigentlich nicht an der Kommunikation liegen, oder?

EDIT:

Ich habe gerade einen anderen Arduino-Sketch probiert.

/* Supports as many analog inputs and analog PWM outputs as possible.
 *
 * This example code is in the public domain.
 */
#include <Firmata.h>

byte analogPin;

void analogWriteCallback(byte pin, int value)
{
    pinMode(pin,OUTPUT);
    analogWrite(pin, value);
}

void setup()
{
    Firmata.setFirmwareVersion(0, 1);
    Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
    Firmata.begin(57600);
}

void loop()
{
    while(Firmata.available()) {
        Firmata.processInput();
    }
    for(analogPin = 0; analogPin < TOTAL_ANALOG_PINS; analogPin++) {
        Firmata.sendAnalog(analogPin, analogRead(analogPin)); 
    }
}

Hiermit werden die richtigen Werte geliefert, aber leider ziemlich langsam, es dauert also immer fast eine Sekunde bis Processing die Änderung mitbekommt.

Fehlen noch irgendwelche Informationen? Oder habt ihr nur keine Idee woran es liegen könnte? Wäre euch echt dankbar wenn ihr mir antworten könntet :) Grüße, KloolK

Also zuerst mal funktioniert das ganze bei mir nur, wenn ich den Arduino mit 57600 baud initialisiere:

void setup() {
  arduino = new Arduino(this, Arduino.list()[1], 57600);
  arduino.pinMode(ledPin, Arduino.OUTPUT);
  arduino.pinMode(potiPin, Arduino.INPUT);
}

Sonst kommt nur Datenmüll in Processing an.

Ein bisschen weiteren Geschwindigkeitszuwachs erhält man, wenn man im Firmata-Sketch nicht benötigte Analog-Pins nicht abfragen lässt. Willst du z.B. nur AnalogIn 0 abfragen, soll der Arduino für 1-5 natürlich auch nicht unbedingt Daten schicken (was natürlich alles Zeit in Anspruch nimmt). Also im Firmata Sketch (hier im SimpleAnalog Sketch aus Sketchbook->Examples->Firmata->SimpleAnalogFirmata, das ist der, den du auch benutzt) einfach

void loop()
{
    while(Firmata.available()) {
        Firmata.processInput();
    }
    for(analogPin = 0; analogPin < TOTAL_ANALOG_PINS; analogPin++) {
        Firmata.sendAnalog(analogPin, analogRead(analogPin)); 
    }
}

umändern in

void loop()
{
    while(Firmata.available()) {
        Firmata.processInput();
    }
    for(analogPin = 0; analogPin < 1; analogPin++) {
        Firmata.sendAnalog(analogPin, analogRead(analogPin)); 
    }
}

Damit spart man sich schon mal 5 AnalogIn-Polls und die entsprechenden Meldungen an Processing.

Wenn du dann noch einen kurzen Delay zwischen den AnalogIn-Abfragen im Firmata-Sketch einfügst so wie hier:

if((millis()-prevmillis)>10){
      prevmillis = millis();
      for(analogPin = 0; analogPin < 1; analogPin++) {
          Firmata.sendAnalog(analogPin, analogRead(analogPin)); 
      }
    }

dann muss der Arduino nur alle 10 Millisekunden die Analogdaten senden, was für dich wohl kaum merkbar sein dürfte (habs hier selbst ausprobiert, ich merke eigentlich keine Verzögerung). Das sorgt dafür, dass die Datenleitung nicht unablässig voll ist, so dass kein Lag entsteht.

Hier noch mal alle Codes wie ich sie jetzt hier vor mir sehe:

Arduino Firmata Sketch (SimpleAnalogFirmata abgeändert):

/* Supports as many analog inputs and analog PWM outputs as possible.
 *
 * This example code is in the public domain.
 */
#include <Firmata.h>

byte analogPin;
int prevmillis;

void analogWriteCallback(byte pin, int value)
{
    pinMode(pin,OUTPUT);
    analogWrite(pin, value);
}

void setup()
{
    Firmata.setFirmwareVersion(0, 1);
    Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
    Firmata.begin(57600);
}

void loop()
{
    while(Firmata.available()) {
        Firmata.processInput();
    }
    if((millis()-prevmillis)>10){
      prevmillis = millis();
      for(analogPin = 0; analogPin < 1; analogPin++) {
          Firmata.sendAnalog(analogPin, analogRead(analogPin)); 
      }
    }
}

und der Processing-Sketch (deiner leicht abgeändert):

import cc.arduino.*;
import processing.serial.*;

int ledPin = 13;
int potiPin = 0;
int potiVal = 0;
int oldpotiVal = 0;

Arduino arduino;

void setup() {
  arduino = new Arduino(this, Arduino.list()[1], 57600);
  arduino.pinMode(ledPin, Arduino.OUTPUT);
  arduino.pinMode(potiPin, Arduino.INPUT);
}

void draw() {
  potiVal = arduino.analogRead(potiPin);
  println(potiVal);
  if((potiVal >= 512) && (oldpotiVal < 512)){ 
    arduino.digitalWrite(ledPin, Arduino.HIGH);
  } else if ((potiVal < 512) && (oldpotiVal >= 512)){
    arduino.digitalWrite(ledPin, Arduino.LOW);
  }
  oldpotiVal = potiVal;
  background(204);
  fill(255,0,0);
  ellipse(50,50,potiVal/10,potiVal/10);
}

Hoffentlich hat dir das weitergeholfen, beachte nur, dass die SimpleAnalogFirmata keine Digital-Pin-Meldungen annimmt, also wird die LED so wohl nicht angehen.

Hups, merke gerade dass das ganze nach etwa 30 Sekunden wieder laggy wird, liegt sicherlich daran, dass prevmillis dann einen rollover auf 0 macht und der Arduino wieder unablässig Daten sendet. Um das Problem müsste man sich wohl noch kümmern…

Edit: so, also wenn du prevmillis als Integer anlegst, dann kann der Wert höchstens 32.768 betragen (also etwa 32 Sekunden in Millisekunden). Nimm einfach statt einer Integer eine Unsigned Long, die kann Werte bis zu 4,294,967,295 speichern. Das umgerechnet in Stunden sind knapp 1200, also würde es erst nach 1200 Stunden wieder laggy werden.

Der Code:

/* Supports as many analog inputs and analog PWM outputs as possible.
 *
 * This example code is in the public domain.
 */
#include <Firmata.h>

byte analogPin;
unsigned long prevmillis;

void analogWriteCallback(byte pin, int value)
{
    pinMode(pin,OUTPUT);
    analogWrite(pin, value);
}

void setup()
{
    Firmata.setFirmwareVersion(0, 1);
    Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
    Firmata.begin(57600);
}

void loop()
{
    while(Firmata.available()) {
        Firmata.processInput();
    }
    if((millis()-prevmillis)>10){
      prevmillis = millis();
      for(analogPin = 0; analogPin < 1; analogPin++) {
          Firmata.sendAnalog(analogPin, analogRead(analogPin));
      }
    }
}

Funkioniert alles, vielen vielen Dank! Das mit der Initialisierung und der Baud-Rate scheint bei mir, wenn ich Firmata.begin(57600) aufrufe, egal zu sein. Bei anderen Werte jedoch nicht. Nochmal vielen Dank für deine Hilfe :)

Hatte gerade letzten Post nochmal modifiziert, da solltest du noch mal nen Blick drauf werfen wenn noch nicht passiert ;)

Freut mich aber dass alles funktioniert.

Ja, habs schon gesehen. Auch das klappt jetzt und 1200 Stunden sind ganz sicher genug^^.