Reading lpd3806 x times a second

Hi, i'm using this script to read encoder (lpd3806) position and writing it to a SD card.

#include <SPI.h>
#include <SD.h>
#define SD_PIN 10
#define encoderPinA 3
#define encoderPinB 2

volatile long pos=0;

File myFile;

void setup() {
  Serial.begin(9600);

  //setup rotary encoder
  pinMode(encoderPinA,INPUT_PULLUP);
  pinMode(encoderPinB,INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(encoderPinA),doEncoderA,CHANGE);
  attachInterrupt(digitalPinToInterrupt(encoderPinB),doEncoderB,CHANGE);

  //setup SD
  if(!SD.begin(SD_PIN)){ while(true); }
  myFile = SD.open("ok.txt", FILE_WRITE);
  
  Serial.println("setup completed");
}

void loop() {
  myFile.print(pos+",");
}


void doEncoderA() {
  // look for a low-to-high on channel A
  if (digitalRead(encoderPinA) == HIGH) {
    // check channel B to see which way encoder is turning
    if (digitalRead(encoderPinB) == LOW) {
      pos = pos + 1;         // CW
    } else {
      pos = pos - 1;         // CCW
    }
  } else {// look for a high-to-low on channel A
    if (digitalRead(encoderPinB) == HIGH) {// check channel B to see which way encoder is turning
      pos = pos + 1;          // CW
    } else {
      pos = pos - 1;          // CCW
    }
  }  
}

void doEncoderB() { 
  // look for a low-to-high on channel B
  if (digitalRead(encoderPinB) == HIGH) {
    // check channel A to see which way encoder is turning
    if (digitalRead(encoderPinA) == HIGH) {
      pos = pos + 1;         // CW
    } else {
      pos = pos - 1;         // CCW
    }
  } else { // Look for a high-to-low on channel B
    // check channel B to see which way encoder is turning
    if (digitalRead(encoderPinA) == LOW) {
      pos = pos + 1;          // CW
    } else {
      pos = pos - 1;          // CCW
    }
  }
}

Is it possible to write the position of the encoder only x times a seconds? for example 50 times a second?
What throws me off is that i am reading the position with interrupts and for this reason i'm sure delays won't work. I don't know what else to try.

I don't know if I understood your difficulty well, but see if the code meets your need.

#include <SPI.h>
#include <SD.h>
#define SD_PIN 10
#define encoderPinA 3
#define encoderPinB 2

volatile long pos=0;

unsigned long lastMillis = 0;
unsigned long myTime = 20; //  1000 = 1 second    50 times    1000/50 = 20 mS

File myFile;

void setup() {
  Serial.begin(9600);

  //setup rotary encoder
  pinMode(encoderPinA,INPUT_PULLUP);
  pinMode(encoderPinB,INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(encoderPinA),doEncoderA,CHANGE);
  attachInterrupt(digitalPinToInterrupt(encoderPinB),doEncoderB,CHANGE);

  //setup SD
  if(!SD.begin(SD_PIN)){ while(true); }
  myFile = SD.open("ok.txt", FILE_WRITE);
  
  Serial.println("setup completed");
}

void loop() {
  if(millis() - lastMillis >= myTime)
  {
  myFile.print(pos+",");
  lastMillis = millis();
  //Serial.println((lastMillis));
  }
}


void doEncoderA() {
  // look for a low-to-high on channel A
  if (digitalRead(encoderPinA) == HIGH) {
    // check channel B to see which way encoder is turning
    if (digitalRead(encoderPinB) == LOW) {
      pos = pos + 1;         // CW
    } else {
      pos = pos - 1;         // CCW
    }
  } else {// look for a high-to-low on channel A
    if (digitalRead(encoderPinB) == HIGH) {// check channel B to see which way encoder is turning
      pos = pos + 1;          // CW
    } else {
      pos = pos - 1;          // CCW
    }
  }  
}

void doEncoderB() { 
  // look for a low-to-high on channel B
  if (digitalRead(encoderPinB) == HIGH) {
    // check channel A to see which way encoder is turning
    if (digitalRead(encoderPinA) == HIGH) {
      pos = pos + 1;         // CW
    } else {
      pos = pos - 1;         // CCW
    }
  } else { // Look for a high-to-low on channel B
    // check channel B to see which way encoder is turning
    if (digitalRead(encoderPinA) == LOW) {
      pos = pos + 1;          // CW
    } else {
      pos = pos - 1;          // CCW
    }
  }
}

Ok, Do you know how I can calculate how high I can raise the sampling time? I have problems because of interrupts happening. Encoder i'm using have a response frequency of 0-20KHz

if this is the code in the loop function:

if(millis() - lastMillis >= myTime){
      Serial.print(pos);
      Serial.print(" ");
      Serial.println(millis());
      lastMillis = millis();
  }

I tried to increase the number of samples and these were the results (while moving the encoder so letting there be interrupts).

With myTime=20 (50 samples per seconds):

256 20
427 40
504 60
506 80
497 100
419 120
254 140
-54 160

And this is fine, but going up to 100 samples a second (myTime=10) is showing weaknesses:

178 10
-386 20
-632 30
-927 40
-1244 50
-1646 60
-2026 70
-2313 80
-2518 90
-2733 100
-2960 110
-3195 120
-3430 130
-3689 140
-3904 150
-4077 160
-4213 171

note the 171 at the end, then it starts drifting away.

With 500 samples a second:

...
363 20
401 22
440 24
477 26
514 28
565 31
629 35
685 39
719 44
764 48
789 52
804 56
812 60
....

Seems like i'm not able to control precisely how many samples per second i'm able to take.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.