This is a telescope focuser that controls a stepper via IR. The script moves in increments of 10 up or down (forward or backwards). A counter starts from zero (it must be homed before use). It works fine up until I use the entry() function. Then if I enter a digit higher than the current position (pos), it ends 10 short (or at least that's what the position reads). if the entry is lower, then it's 10 higher than it's supposed to be. The issue appears to be in the 0x0 case that handles repeats (so I can hold the button down). If I comment the case out or simply don't use it by not holding down the buttons during a session, it counts just fine. I'd feel a little better if it's reporting the actual position, instead of the pos being thrown off by 10 each time(this can add up throughout a session if the reported pos doesn't match the actual position). If it's actually moving it to that position, I can live with it by just pressing the button once up or down...other than it being annoying. I eventually want this to be Ascom compliant, but I'll cross that bridge when I get there.
Here's my code. I'm including some comments for troubleshooting purposes.
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <IRremote.hpp>
#include "Stepper.h"
#define IR_RECEIVE_PIN 12
#define STEPS 32 // Number of steps per revolution of Internal shaft
int fwd; // 2048 = 1 Revolution
int rev;
int mspeed = 500;
int stepCount = 0;
int long lastcmd=0;
int light;
int pos=0;
int pspeed;
int MaxPos = 4600;
int limitReached;
int Nav;
int correct;
Stepper small_stepper(STEPS, 8, 10, 9, 11);
LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display
void setup() {
// put your setup code here, to run once:
IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK); // Start the receiver
Serial.begin (9600);
lcd.init(); // initialize the lcd
lcd.backlight();
}
void loop() {
lcd.setCursor(0,0);
//delay(50);
lcd.print("POSITION: ");
lcd.print(pos);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print("SPEED: ");
if(mspeed==500){
lcd.print("HIGH ");
}else{
lcd.print("LOW ");
}
if (IrReceiver.decode()) {
small_stepper.setSpeed(mspeed);
Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX); // Print "old" raw data
IrReceiver.printIRResultShort(&Serial); // Print complete received data in one line
IrReceiver.printIRSendUsage(&Serial); // Print the statement required to send this data
IrReceiver.resume(); // Enable receiving of the next value
switch (IrReceiver.decodedIRData.decodedRawData){
case 0x0:
//problem with off by 10 could be here, probably is
if(lastcmd==0xB946FF00){
// correct = 1; //temp correction
focusIn(10);
// correct = 0;
}
if(lastcmd==0xEA15FF00){
// correct = correct + 10;
// correct = 1;
focusOut(10);
}
break;
case 0xB946FF00: //up
lastcmd=IrReceiver.decodedIRData.decodedRawData;
focusIn(10);
break;
case 0xEA15FF00: //down
lastcmd=IrReceiver.decodedIRData.decodedRawData;
focusOut(10);
break;
case 0xBB44FF00: //left
Serial.print("Speed: Low");
mspeed=100;
break;
case 0xBC43FF00: //right
Serial.print("Speed: High");
mspeed=500;
break;
case 0xBD42FF00: //star (display on/off)
Serial.print("Display on/off");
if(light==1)
{
lcd.noBacklight();
light=0;
}else{
lcd.backlight();
light = 1;
}
break;
case 0xAD52FF00: // Number Sign (Home Position)
goHome();
break;
case 0xB54AFF00:
entry();
break;
default:
// statements
break;
}
// Update readings
Serial.print("POS: ");
Serial.println(pos);
pspeed = mspeed / 10;
Serial.print("Speed: ");
if(mspeed==500){
Serial.println("High");
}else{
Serial.println("Low");
}
}
}
void entry()
{
String MyCode;
int cCode;
int cCheck;
lcd.setCursor(0,0);
lcd.print("ENTER POSITION:");
lcd.setCursor(0,1);
lcd.print(" ");
while (MyCode.length() < 4){
if (IrReceiver.decode()) {
cCheck=IrReceiver.decodedIRData.decodedRawData;
IrReceiver.resume();
switch (IrReceiver.decodedIRData.decodedRawData){
case 0xE916FF00: //1
MyCode=MyCode + "1";
lcd.setCursor(0,1);
lcd.print(MyCode);
break;
case 0xE619FF00: //2
MyCode=MyCode + "2";
lcd.setCursor(0,1);
lcd.print(MyCode);
Serial.println("2 pressed");
break;
case 0xF20DFF00: //3
MyCode=MyCode + "3";
lcd.setCursor(0,1);
lcd.print(MyCode);
break;
case 0xF30CFF00: //
MyCode=MyCode + "4";
lcd.setCursor(0,1);
lcd.print(MyCode);
break;
case 0xE718FF00: //
MyCode=MyCode + "5";
lcd.setCursor(0,1);
lcd.print(MyCode);
break;
case 0xA15EFF00: //
MyCode=MyCode + "6";
lcd.setCursor(0,1);
lcd.print(MyCode);
break;
case 0xF708FF00: //
MyCode=MyCode + "7";
lcd.setCursor(0,1);
lcd.print(MyCode);
break;
case 0xE31CFF00: //
MyCode=MyCode + "8";
lcd.setCursor(0,1);
lcd.print(MyCode);
break;
case 0xA55AFF00: //
MyCode=MyCode + "9";
lcd.setCursor(0,1);
lcd.print(MyCode);
break;
case 0xAD52FF00: //
MyCode=MyCode + "0";
lcd.setCursor(0,1);
lcd.print(MyCode);
break;
case 0xBD42FF00: // exit function
return;
break;
default:
// return;
break;
}
}
}
int test = pos;
cCode=MyCode.toInt();
Serial.println("Code is ");
Serial.println(cCode);
lcd.setCursor(0,0);
lcd.print("FOCUSING TO ");
lcd.setCursor(0,1);
lcd.print("POSITION ");
lcd.print(cCode);
//begin math
if (cCode < pos){
Nav = pos-cCode;
focusIn(Nav);
//pos=cCode; // WARNING this may only fix the readout
//This is code to correct (possibly)
// if (correct=1){
// focusOut(10);
// }
}
if (cCode > pos){
Nav = cCode-pos;
focusOut(Nav);
//pos=cCode; // WARNING this may only fix the readout UPDATE oddly, this didn't fix
//if (correct=1){
// focusIn(10);
// }
}
Serial.print("NAV: ");
Serial.println(Nav);
Serial.print("Test: ");
Serial.println(test);
}
void limit ()
{
lcd.setCursor(0,0);
lcd.print("LIMIT REACHED!");
lcd.setCursor(0,1);
lcd.print(" ");
delay(1000);
}
void focusIn(int distance) {
limitReached=pos-distance;
if(pos <= 0){
limit();
}else{
small_stepper.step(-distance);
Serial.print("Moved -");
Serial.println(distance);
// delay(10);
pos=pos-distance;}
}
void focusOut(int distance){
limitReached=pos+distance;
if(limitReached > MaxPos){
limit();
}else{
small_stepper.step(distance);
Serial.print("Moved +");
Serial.println(distance);
// delay(10);
pos=pos+distance;}
}
void goHome(){
int x=0;
lcd.setCursor(0,0);
lcd.print("MOVE HOME AND ");
lcd.setCursor(0,1);
lcd.print("THEN PRESS OK");
while (x=!0){
if (IrReceiver.decode()) {
small_stepper.setSpeed(mspeed);
IrReceiver.printIRResultShort(&Serial); // Print complete received data in one line
IrReceiver.printIRSendUsage(&Serial); // Print the statement required to send this data
IrReceiver.resume(); // Enable receiving of the next value
switch (IrReceiver.decodedIRData.decodedRawData){
case 0x0:
if(lastcmd==0xB946FF00){
small_stepper.step(-10);
delay(10);
}
if(lastcmd==0xEA15FF00){
small_stepper.step(10);
delay(10);
}
break;
case 0xB946FF00: //up
lastcmd=IrReceiver.decodedIRData.decodedRawData;
small_stepper.step(-10);
delay(10);
break;
case 0xEA15FF00: //down
lastcmd=IrReceiver.decodedIRData.decodedRawData;
small_stepper.step(10);
delay(10);
break;
case 0xBF40FF00:
pos=0;
return;
break;
}}}
}
Thanks. I'm migrating from another language so at the moment, I chose the quickest option I knew from memory. Upon testing the interface in the daylight, I did notice something. whenever I press any key, it nudges the motor by one step (or 10, rather). Whether it be for speed (mspeed) or navigation. Something in the repeat part of the case statement is causing it I think.
I think I may have fixed it. Issue was for some reason with the lastcmd = IrReceiver.decodedIRData.decodedRawData line in each case. I started by removing it and placing one right after the main IF. It worked, but it lagged due to the constant reading. So I placed it in an IF of it's own and that seems to have done it. I don't know why it was an issue, but most importantly, it appears to be working as it should now. Here's the code with alterations.
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <IRremote.hpp>
#include "Stepper.h"
#define IR_RECEIVE_PIN 12
#define STEPS 32 // Number of steps per revolution of Internal shaft
int fwd; // 2048 = 1 Revolution
int rev;
int mspeed = 500;
int stepCount = 0;
int long lastcmd = 0;
int light;
int pos = 0;
int pspeed;
int MaxPos = 4600;
int limitReached;
int Nav;
int correct;
Stepper small_stepper(STEPS, 8, 10, 9, 11);
LiquidCrystal_I2C lcd(0x27, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display
void setup() {
// put your setup code here, to run once:
IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK); // Start the receiver
Serial.begin (9600);
lcd.init(); // initialize the lcd
lcd.backlight();
}
void loop() {
lcd.setCursor(0, 0);
//delay(50);
lcd.print("POSITION: ");
lcd.print(pos);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print("SPEED: ");
if (mspeed == 500) {
lcd.print("HIGH ");
} else {
lcd.print("LOW ");
}
if (IrReceiver.decode()) {
small_stepper.setSpeed(mspeed);
Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX); // Print "old" raw data
IrReceiver.printIRResultShort(&Serial); // Print complete received data in one line
IrReceiver.printIRSendUsage(&Serial); // Print the statement required to send this data
if (IrReceiver.decodedIRData.decodedRawData) {
lastcmd = IrReceiver.decodedIRData.decodedRawData;
}
IrReceiver.resume(); // Enable receiving of the next value
switch (IrReceiver.decodedIRData.decodedRawData) {
case 0x0:
if (lastcmd == 0xB946FF00) {
focusIn(10);
}
if (lastcmd == 0xEA15FF00) {
focusOut(10);
}
break;
case 0xB946FF00: //up
focusIn(10);
break;
case 0xEA15FF00: //down
focusOut(10);
break;
case 0xBB44FF00: //left
Serial.print("Speed: Low");
mspeed = 100;
break;
case 0xBC43FF00: //right
Serial.print("Speed: High");
mspeed = 500;
break;
case 0xBD42FF00: //star (display on/off)
Serial.print("Display on/off");
if (light == 1)
{
lcd.noBacklight();
light = 0;
} else {
lcd.backlight();
light = 1;
}
break;
case 0xAD52FF00: // Number Sign (Home Position)
goHome();
break;
case 0xB54AFF00:
entry();
break;
default:
break;
}
// Update readings
Serial.print("POS: ");
Serial.println(pos);
pspeed = mspeed / 10;
Serial.print("Speed: ");
if (mspeed == 500) {
Serial.println("High");
} else {
Serial.println("Low");
}
}
}
void entry()
{
String MyCode;
int cCode;
int cCheck;
lcd.setCursor(0, 0);
lcd.print("ENTER POSITION:");
lcd.setCursor(0, 1);
lcd.print(" ");
while (MyCode.length() < 4) {
if (IrReceiver.decode()) {
cCheck = IrReceiver.decodedIRData.decodedRawData;
IrReceiver.resume();
switch (IrReceiver.decodedIRData.decodedRawData) {
case 0xE916FF00: //1
MyCode = MyCode + "1";
lcd.setCursor(0, 1);
lcd.print(MyCode);
break;
case 0xE619FF00: //2
MyCode = MyCode + "2";
lcd.setCursor(0, 1);
lcd.print(MyCode);
Serial.println("2 pressed");
break;
case 0xF20DFF00: //3
MyCode = MyCode + "3";
lcd.setCursor(0, 1);
lcd.print(MyCode);
break;
case 0xF30CFF00: //
MyCode = MyCode + "4";
lcd.setCursor(0, 1);
lcd.print(MyCode);
break;
case 0xE718FF00: //
MyCode = MyCode + "5";
lcd.setCursor(0, 1);
lcd.print(MyCode);
break;
case 0xA15EFF00: //
MyCode = MyCode + "6";
lcd.setCursor(0, 1);
lcd.print(MyCode);
break;
case 0xF708FF00: //
MyCode = MyCode + "7";
lcd.setCursor(0, 1);
lcd.print(MyCode);
break;
case 0xE31CFF00: //
MyCode = MyCode + "8";
lcd.setCursor(0, 1);
lcd.print(MyCode);
break;
case 0xA55AFF00: //
MyCode = MyCode + "9";
lcd.setCursor(0, 1);
lcd.print(MyCode);
break;
case 0xAD52FF00: //
MyCode = MyCode + "0";
lcd.setCursor(0, 1);
lcd.print(MyCode);
break;
case 0xBD42FF00: // exit function
return;
break;
default:
// return;
break;
}
}
}
int test = pos;
cCode = MyCode.toInt();
Serial.println("Code is ");
Serial.println(cCode);
lcd.setCursor(0, 0);
lcd.print("MOVING... ");
lcd.setCursor(0, 1);
lcd.print("TARGET: ");
lcd.print(cCode);
//begin math
if (cCode < pos) {
Nav = pos - cCode;
focusIn(Nav);
}
}
if (cCode > pos) {
Nav = cCode - pos;
focusOut(Nav);
}
}
Serial.print("NAV: ");
Serial.println(Nav);
Serial.print("Test: ");
Serial.println(test);
}
void limit ()
{
lcd.setCursor(0, 0);
lcd.print("LIMIT REACHED!");
lcd.setCursor(0, 1);
lcd.print(" ");
delay(1000);
}
void focusIn(int distance) {
limitReached = pos - distance;
if (pos <= 0) {
limit();
} else {
small_stepper.step(-distance);
Serial.print("Moved -");
Serial.println(distance);
// delay(10);
pos = pos - distance;
}
}
void focusOut(int distance) {
limitReached = pos + distance;
if (limitReached > MaxPos) {
limit();
} else {
small_stepper.step(distance);
Serial.print("Moved +");
Serial.println(distance);
// delay(10);
pos = pos + distance;
}
}
void goHome() {
int x = 0;
lcd.setCursor(0, 0);
lcd.print("MOVE HOME AND ");
lcd.setCursor(0, 1);
lcd.print("THEN PRESS OK");
while (x = !0) {
if (IrReceiver.decode()) {
small_stepper.setSpeed(mspeed);
IrReceiver.printIRResultShort(&Serial); // Print complete received data in one line
IrReceiver.printIRSendUsage(&Serial); // Print the statement required to send this data
IrReceiver.resume(); // Enable receiving of the next value
switch (IrReceiver.decodedIRData.decodedRawData) {
case 0x0:
if (lastcmd == 0xB946FF00) {
small_stepper.step(-20);
delay(10);
}
if (lastcmd == 0xEA15FF00) {
small_stepper.step(10);
delay(20);
}
break;
case 0xB946FF00: //up
lastcmd = IrReceiver.decodedIRData.decodedRawData;
small_stepper.step(-10);
delay(10);
break;
case 0xEA15FF00: //down
lastcmd = IrReceiver.decodedIRData.decodedRawData;
small_stepper.step(10);
delay(10);
break;
case 0xBF40FF00:
pos = 0;
return;
break;
}
}
}
}