I have to build a meteorological statation for a university project, it must show wind speed and direction, temperature and humidity on a lcd display. I have already implemented a code that works with a mechanical rotary encoder(mouse wheel) , but when I trade it by the optical one it gives same reading for different shaft rotation speeds. Per exemple, if I spin it prety slow it gives 360 degrees in a quarter of circle and if I do it faster i have 160 degrees in a full turn.
The encoder is tamagawa FA-coder TS5314N 2500 C/T
I started to use arduino this semester in this specific subject, so don't have much experience. I hope that you guys can help me.
I have annexed the data sheet(my encoder model is in the pages 12 and 13), the isolated code that i am using in the encoder and the entire code of the station (it can be usefull for someone with problems in another part of this kind of project).
Thanks for the attention .
datasheet: http://www.tamagawa-seiki.com/pdf/download/1228N55EJ_shusei.pdf
(entire code)
#include <Encoder.h>
#define ENCODER_OPTIMIZE_INTERRUPTS
#include "DHT.h"
#include <LiquidCrystal.h>
#define buttom1 13
#define DHTPIN 8
#define DHTTYPE DHT22
#define PINA 2
#define PINB 4
#define INTERRUPT 0
volatile byte half_revolutions;
unsigned int rpm;
unsigned long timeold;
volatile boolean fired;
volatile boolean up;
DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal lcd(12,11,7,6,5,10);
boolean lastButton = LOW;
boolean currentButton = LOW;
boolean lastlcd = true;
int b1 = 0;
unsigned long previousMillis = 0;
unsigned long currentMillis = 0;
int encoderStepsPerRevolution= 2500;
float angles=0;
float angle=0;
void isr ()
{
if (digitalRead (PINA))
up = digitalRead (PINB);
else
up = !digitalRead (PINB);
fired = true;
}
void setup() {
lcd.begin(16,2);
dht.begin();
lcd.setCursor(0,0);
lcd.print("meteorological");
lcd.setCursor(0,1);
lcd.print("station");
delay(5000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("MedTerm ENG03108");
delay(5000);
lcd.clear();
digitalWrite (PINA, HIGH); // enable pull-ups
digitalWrite (PINB, HIGH);
attachInterrupt (INTERRUPT, isr, CHANGE);
attachInterrupt(1, rpm_fun, RISING);
half_revolutions = 0;
rpm = 0;
timeold = 0;
Serial.begin(115200);
}
void rpm_fun()
{
half_revolutions++;
//Each rotation, this interrupt function is run twice
}
boolean debounce(boolean last)
{
boolean current = digitalRead(buttom1);
if (last != current)
{
currentMillis = millis();
if (currentMillis - previousMillis>=5){
previousMillis=currentMillis;
current = digitalRead(buttom1);
}
}
return current;
}
void loop(){
currentButton = debounce(lastButton);
if (lastButton == LOW && currentButton == HIGH)
{
if (lastlcd) lastlcd = false;
else lastlcd = true;
}
lastButton = currentButton;
if (lastlcd)
{
static long rotaryCount = 0;
if (fired)
{
if (up)
rotaryCount++;
else
rotaryCount--;
fired = false;
}
// end if fired
angles= 2*rotaryCount;
angle=abs(angles);
if (angle>=360)
{
rotaryCount=0;
}
if (half_revolutions >= 20) {
//Update RPM every 20 counts, increase this for better RPM resolution,
//decrease for faster update
rpm = 30*1000/(millis() - timeold)*half_revolutions;
timeold = millis();
half_revolutions = 0;
}
{
char dirF[6];
char velF[6];
dtostrf(angle, 1, 3, dirF);
dtostrf(rpm, 1, 1, velF);
lcd.setCursor(0,0);
lcd.print("Dir: ");
lcd.print(dirF);
lcd.print((char)223);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print("Vel: ");
lcd.print(velF);
lcd.print("m/s ");
}
}
else
{
float temperature, humidity;
humidity = dht.readHumidity();
temperature = dht.readTemperature();
char tempF[6];
char humF[6];
dtostrf(temperature, 5, 2, tempF);
dtostrf(humidity, 2, 0, humF);
currentMillis = millis();
if (currentMillis - previousMillis>=2000){
previousMillis=currentMillis;
lcd.clear();
}
lcd.setCursor(0,0);
lcd.print("Temp: ");
lcd.print(tempF);
lcd.print((char)223);
lcd.print("C ");
lcd.setCursor(0,1);
lcd.print("Humi: ");
lcd.print(humF);
lcd.print("% ");
}
}
(Isolated encoder code)
#include "Arduino.h"
#include <digitalWriteFast.h>
#include <Encoder.h>
#define ENCODER_OPTIMIZE_INTERRUPTS
#include <LiquidCrystal.h>
volatile boolean fired;
volatile boolean up;
LiquidCrystal lcd(12,11,7,6,5,10);
float angles=0;
float angle=0;
#define PINA 2
#define PINB 4
#define PINC 9
#define INTERRUPT 0 // that is, pin 2
// Interrupt Service Routine for a change to encoder pin A
void isr ()
{
if (digitalRead (PINA))
up = digitalRead (PINB);
else
up = !digitalRead (PINB);
fired = true;
} // end of isr
void setup ()
{
lcd.begin(16,2);
digitalWrite (PINA, HIGH); // enable pull-ups
digitalWrite (PINB, HIGH);
attachInterrupt (INTERRUPT, isr, CHANGE); // interrupt 0 is pin 2, interrupt 1 is pin 3
Serial.begin (250000);
} // end of setup
void loop ()
{
static long rotaryCount = 0;
if (fired)
{
if (up)
rotaryCount++;
else
rotaryCount--;
fired = false;
float angles= ( rotaryCount%encoderStepsPerRevolution) * 360/encoderStepsPerRevolution;
Serial.print ("Count = ");
lcd.setCursor(1,0);
lcd.print (angle);
angle= 0.144*rotaryCount;
if (angle>=360)
{
rotaryCount=0;
}
} // end if fired
} // end of loop
Moderator edit:
</mark> <mark>[code]</mark> <mark>
</mark> <mark>[/code]</mark> <mark>
tags added.
encoderisolado.ino (1.22 KB)
codigoestacao.ino (3.07 KB)