Comparing values over time

Hi,

I'm streaming data from a rotary encoder connected to and Arduino through the serial port into Processing - lets call this number 'rotaryNum'

rotaryNum will only ever be between 0-15. Every time this value changes, I want to start a 3 second timer. When the timer finishes, I want to compare the difference between rotaryNum before the timer started, and when the timer finished.

What is the best way to do this?

I've added some code where I've tried to do this, but I don't really know how to do it. Would anyone have any ideas on how best to achieve what I'm attempting to do?

import processing.serial.*;

Serial myPort;

float value;
float currentValue;

int savedTime;
int totalTime = 3000;


void setup() {
   size(400,400);
  frameRate(25);
  println(Serial.list());
  myPort = new Serial(this, Serial.list()[1], 9600);
}


void draw() {
 background(0);  

 String pulses_raw = myPort.readStringUntil('\n'); //read until the new line, like print ln
  int passedTime = millis() - savedTime;

  if (pulses_raw != null) {
    pulses_raw = trim(pulses_raw);
    float rotaryNum = float(pulses_raw); 
    println(rotaryNum);

    //timer = millis();


    currentValue = rotaryNum;

    if(passedTime > totalTime){
      println("currentValue is = " + currentValue);

        if( (rotaryNum >= (currentValue + 2)) && (rotaryNum <= (currentValue + 2)) ){
          println("pulses is more than currentValue + or - 2"); 
          background(random(255));
          savedTime = millis();
        }
    }
  }
}

Answers

  • edited March 2014 Answer ✓

    I've got some examples that designates a function to run continuously apart from draw() by using thread(""):


    Timer Example I:


    /** 
     * Timer Example (v1.0)
     * by GoToLoop (2013/Oct)
     * 
     * forum.processing.org/two/discussion/110/trigger-an-event
     */
    
    final int TIMER = 2*60 * 1000;  // 2 minutes
    boolean hasTriggered, isEnabled = true;
    
    void setup() {
      frameRate(1);
      fill(#FFFF00);
      textSize(32);
      textAlign(CENTER, CENTER);
    
      thread("timer");
    }
    
    void draw() {
      final String msg = nf(minute(), 2) + ":" + nf(second(), 2);
    
      background(0);
      text(msg, width>>1, height>>1);
    
      if (hasTriggered) {
        hasTriggered = false;
        logger("Triggered @ " + msg);
      }
    }
    
    void timer() {
      while (isEnabled) {
        hasTriggered = true;
        delay(TIMER);
      }
    }
    
    static final void logger(String log) {
      println(log);
    }
    


    Timer Example II:


    /** 
     * Timer Example 2 (v1.01)
     * by  GoToLoop (2013/Oct)
     * 
     * forum.processing.org/two/discussion/110/trigger-an-event
     */
    
    final static int TIMER = 1*60 * 1000;  // 1 minute
    
    static boolean isEnabled = true;
    static String msg;
    
    void setup() {
      frameRate(1);
      fill(#FFFF00);
      textSize(32);
      textAlign(CENTER, CENTER);
    
      thread("timer");
    }
    
    void draw() {
      msg = nf(minute(), 2) + ":" + nf(second(), 2);
    
      background(0);
      text(msg, width>>1, height>>1);
    }
    
    void timer() {
      while (isEnabled) {
        delay(TIMER);
        logger();
      }
    }
    
    static final void logger() {
      println("Triggered @ " + msg);
    }
    


    Timed XML Fetcher:


    /** 
     * Timed XML Fetcher (v2.12)
     * by  alless0 (2013/Dec)
     * mod GoToLoop
     * 
     * forum.processing.org/two/discussion/1891/
     * adding-intervals-for-fetching-rss-data
     */
    
    static final int MAX_ROWS = 9, INTERVAL = 5*60*1000; // 5 minutes
    static final int DIM = 48, GAP = 65;
    static final color BG = 0300, FG = 0;
    
    static final String URL  = "http://" + "www.hamshahrionline.ir/rss";
    static final String DIR  = "channel/item/title";
    static final String NAME = "news-", EXT = ".png";
    
    static PGraphics pg;
    static boolean isActive = true;
    
    void setup() {
      size(1280, 720);
      frameRate(60);
      noLoop();
    
      pg = createGraphics(width, height);
    
      pg.beginDraw();
      pg.smooth(4);
      pg.fill(FG);
      pg.textFont(createFont("Nazanin", DIM));
      pg.textAlign(RIGHT, TOP);
      pg.endDraw();
    
      thread("xmlFetchTimer");
    }
    
    void draw() {
      background(pg);
      //pg.save(dataPath(NAME + nf(frameCount, 3) + EXT));
      saveFrame(dataPath(NAME + "###" + EXT));
    }
    
    void xmlGetAndRender() {
      final XML[] elems = loadXML(URL).getChildren(DIR);
      final int len = min(elems.length, MAX_ROWS);
      final int w = width - 5;
    
      pg.background(BG);
      for (int i = 0; i != len; pg.text(elems[i++].getContent(), w, GAP*i));
      pg.endDraw();
    }
    
    void xmlFetchTimer() {
      delay(1000);
      frameCount = 1;
    
      while (isActive) {
        xmlGetAndRender();
        redraw();
        delay(INTERVAL);
      }
    }
    

  • Hi,

    Just getting a change to test this now. Well, the timer works great, so many thanks for that :) I used Example II.

    However, I'm having a metal block in trying to save the number in a variable before the timer starts, and then comparing it to the current value of the number when the timer finished. I'm baffled. Any ideas on how to do this?

  • edited March 2014

    A function called by thread("") can't receive passed arguments! So it's pretty much dependent on "global" variables. :-S

    @ Example II, it calls target function logger() after each delay().
    Issue is, since timer() itself is void of passed parameters, there's no exclusive parameters it can invoke logger() with! :-?

    On the other hand @ Example I, timer() assigns true to a boolean in order to flag the INTERVAL time has been reached.
    Then draw() keeps checking on that "global" boolean. Once it turns out true, it sets it again to false and invokes
    logger(), passing more up-to-date parameters!

    Therefore, I advise you to try the more flexible Example I out. You can also make the check within draw() to set a "start" value too.

  • Hi,

    Thanks for the advice about the timers - I never had much of an understanding of them.

    In the end I managed to hack together a solution using an array, so I didn't utilize those timers. To give you an explination:

    I'm reading serial data from Arduino, and putting them into the array called 'churnArray'. I put them in at the start, and after I've put one in I shorten it. I then compare the first character in the array to the last, and if they're different I know that there has been a change. It probalby isn't the best way to do it, especially seeing as I have a frameRate(1); which means I cant do much with graphics on screen, but otherwise works!

    Thanks for your help!

    int[] churnArray = {0,0,0,0};
    
    String pulses_raw = myPort.readStringUntil('\n');
      if(pulses_raw != null){
        pulses_raw = trim(pulses_raw);
        churnInt = int(pulses_raw);
      }
    churnArray = splice(churnArray, churnInt, 0);
    churnArray = shorten(churnArray);
    
      //if there is no change
      if(churnArray[0] == churnArray[3]){
        println("stop");
        minim.stop();
        playerPlaying = false;
      }
      //if there is a change
      if(churnArray[0] != churnArray[3]){
        println("play");
        churningStarted();
    
        player.play();
        playerPlaying = true;
      }
    
Sign In or Register to comment.