Saving a pulse/count position from my motor encoder

Hi!

I have a quite simple program in Arduino. :slight_smile:
With a I2C 2x16 LCD display, that displays the pulses i get from my motor with a added rotary encoder.
There is a button that when held starts the motor at one direction.
And another button thats starts the motor at the other direction.
There is a H-bridge in between to drive the 12V motor.

The function I'd love to have is a button to save a position, only one or max two positions.
And then when the motor go over this position it should stop, and then I need to lift and press the button again to make it continue to go again.

So the positionsave inserts a kind of 'pause'. :o
It would be nice if this could remain in memory when turning the device off and on again.

Thanks beforehand.

Thanks beforehand.

Your welcome.

What is the problem? Reading the encoder isn't the problem. Detecting switch presses isn't the problem. Saving the data to, and reading it from, EEPROM isn't the problem.

I'm a newbie.
There's the problem :stuck_out_tongue:

I dont know what to do, and what order to place it.
If someone could point me in the right direction it would fantastic.

Unikron:
If someone could point me in the right direction it would fantastic.

Start by helping us to help you. Give us useful information.

Post your program and tell us what it actually does and what you want it to do that is different.

If you are using a DC motor it will be very difficult (next to impossible, with simple code) to make it stop at a specific point. What sort of position error is acceptable?

Are you using an absolute-position encoder, or a much more common relative-position encoder. If you are using a relative-position encoder you will need some method to re-establish the zero position every time you restart the Arduino.

...R

Here is pic 1

Image from Reply #4 so we don't have to download it. See this Simple Image Guide

...R

Your picture does not answer any of the questions in Reply #3.

And, while it is a nice piece of photography, it does not convey much of the sort of information needed to help you. A photo of a simple pencil drawing of the circuit would be much more helpful. Technical questions need technical information.

It looks like you have a beam-break system that is triggered by a propeller. That is NOT an absolute position encoder.

...R

OK, try again. Here are two pics.
Gonna make them visible here in a moment...

I will wait for you to make your images visible.

However the questions I posed in Reply #3 do not require pictures for their answers.

...R

So! Now I know how to post the pictures correctly. Sorry for that!
Here is the code, sorry its not in english.

So in short, it counts all the pulses the motor spins, wich is displayed on the LCD (I2C - 2x16).
It has button for turning at one or another direction.
It has a H-bridge for the 12V motor.

I want to save the position, so that when the motor is going by this position again it stops.

//  ---- MOTOR CONST INTARNA  ----
const int controlPin1 = 7;
const int controlPin2 = 6;
const int enablePin = 9;


#include <Wire.h>
#include <LiquidCrystal_I2C.h>


// DESSA TILLHÖR GRAFIK O PULSRÄKNINGEN
char lineText[]="  Hoy! Denna text syns ingenstans.  ";
int sensor01;
int sensor02;
int stepOld;
int step;
long PulseCount;


// ---- MOTOR TEST INT ---------------------------------------------------------------------------------
int intest1Pin = 4;        // KNAPP 1  -  Kabel GRÅ   - Går åt plus hållet    - UPP
int intest2Pin = 5;        // KNAPP 2  -  Kabel GRÖN  - Går åt minus hållet   - NER
int intest3Pin = 10;       // KNAPP 3  -  Kabel SVART - Ej något än
int intest4Pin = 11;       // KNAPP 4  -  Kabel BLÅ   - Ej något än
int stopsensor2Pin = 8;    // SENSOR   -  Kabel GRÅ   - Enskild sensor - UPP STOPP
int stopsensor1Pin = 12;   // SENSOR   -  Kabel GRÖN  - Enskild sensor - NER STOPP
int val = 0;

int tonePin = 13;          // --- BEEPER ---





// DESSA TILLHÖR GRAFIK O PULSRÄKNINGEN - I2C
// initialize the library with the numbers of the interface pins
// 0x27 adressen hittades via I2C scanner på den med svart tejp - De andra hade 0x3F
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); 

// Aktivera denna rad, och av-avaktivera den ovanför, om någon av de andra I2C displayerna ska användas
// LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); 







// DESSA TILLHÖR GRAFIK O PULSRÄKNINGEN
#define SENSOR_A 3
#define SENSOR_B 2

void checkState()
{
sensor01 = digitalRead(SENSOR_A);
sensor02 = digitalRead(SENSOR_B);

if(sensor01 == 1 && sensor02 == 1){
  step = 0;
  if(stepOld == 1){
    PulseCount--;
  }
  if(stepOld == 3){
    PulseCount++;
  }
  stepOld = 0;
}

if(sensor01 == 0 && sensor02 == 1){
  step = 1;
  if(stepOld == 2){
    PulseCount--;
  }
  if(stepOld == 0){
    PulseCount++;
  }
  stepOld = 1;
}

if(sensor01 == 0 && sensor02 == 0){
  step = 2;
  if(stepOld == 3){
    PulseCount--;
  }
  if(stepOld == 1){
    PulseCount++;
  }
  stepOld = 2;
}

if(sensor01 == 1 && sensor02 == 0){
  step = 3;
  if(stepOld == 0){
    PulseCount--;
  }
  if(stepOld == 2){
    PulseCount++;
  }
  stepOld = 3;
}
}


// VOID SETUP - KÖRS BARA EN GÅNG I BÖRJAN, EN FÖRBEREDELSE, LOOP ÄR EXEKVERING OCH GÖR DET MESTA JOBBET
// DESSA TILLHÖR GRAFIK O PULSRÄKNINGEN

void setup() 
{
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print a message to the LCD.
lcd.setCursor(0, 0);
lcd.print("                ");
lcd.setCursor(0, 1);
lcd.print("                ");

attachInterrupt(0, checkState, CHANGE);
attachInterrupt(1, checkState, CHANGE);

PulseCount = 0;





// TEST MOTOR  - VOID SETUP ---------------------------------------------------------------------------------
pinMode(intest1Pin, INPUT);         //Declarar denna som input  UNO input är 4    Knapp 1   Grå     UPP
pinMode(intest2Pin, INPUT);         //Declarar denna som input  UNO input är 5    Knapp 2   Grön    NER
pinMode(intest3Pin, INPUT);         //Declarar denna som input  UNO input är 10   Knapp 3   Svart   Ej något än
pinMode(intest4Pin, INPUT);         //Declarar denna som input  UNO input är 11   Knapp 4   Blå     Ej något än

pinMode(stopsensor1Pin, INPUT);     //Declarar denna som input  UNO input är 12   grön
pinMode(stopsensor2Pin, INPUT);     //Declarar denna som input  UNO input är 8    grå

// Högtalare
pinMode(tonePin, OUTPUT);


//  ---- LCD start presentationen
{

lcd.setCursor(2, 0);
lcd.print("PROTOTYPE"); 
delay(500);
// lcd.clear();

lcd.setCursor(11, 1);
lcd.print("9");
delay(100);

lcd.setCursor(11, 1);
lcd.print("90");
delay(100);

lcd.setCursor(11, 1);
lcd.print("90E");
delay(900);
lcd.clear();

lcd.setCursor(2, 0);
lcd.print("Prototype 1.0");
delay(200);

lcd.setCursor(0, 1);
lcd.print("www.");
delay(100);

lcd.setCursor(12, 1);
lcd.print(".se");
delay(100);

lcd.setCursor(0, 1);
lcd.print("www.PROTOTYPE.se");
delay(250);

lcd.setCursor(0, 1);
lcd.print("www.PROTOTYPE.se");
delay(800);
lcd.clear();

}
}





void loop()


{

// DESSA TILLHÖR GRAFIK O PULSRÄKNINGEN
// LCD set the cursor to column 0, line 1 (note: line 1 is the second row, since counting begins with 0):

lcd.setCursor(0, 0);

lcd.print("Pulses:");
if(PulseCount > -1){
  lcd.print(" ");
}

if(PulseCount < 10 && PulseCount > -10){
  lcd.print(" ");
}

if(PulseCount < 100 && PulseCount > -100){
  lcd.print(" ");
}

lcd.print(PulseCount);
if(sensor01 == 1){
  lcd.print(" HIGH");
}
else{
  lcd.print(" LOW ");
}

lcd.setCursor(0, 1);

if(sensor02 == 1){
  lcd.print("            HIGH");
}
else{
  lcd.print("            LOW ");
}






//  ---- MOTORNS VOID LOOP  - KNAPPSTYRNINGEN TILL MOTORERNA ----

// intest 1 ÅKER UPP
// intest 2 ÅKER NER
// stopsensor1Pin heter stoppsensorn som hindrar UPP
// stopsensor2Pin heter stoppsensorn som hindrar NED

{

// ---- ÅKER UPP ----
val = digitalRead(intest1Pin);         // UPP - Läser input värde
if (val == HIGH)                       // Checkar om knappen trycks
{                     
digitalWrite(controlPin1, HIGH);       
digitalWrite(controlPin2, LOW);

// -- Detta är sensorn som, om täcks, hindrar motorn från att åka ner
{
val = digitalRead(stopsensor2Pin);         // Sensorn som stoppar motorn
if (val == HIGH) {                     
digitalWrite(controlPin1, LOW);

// -- Dessa 3 rader visar STOP när sensorn stoppar nedgång - delay ställer flimret men slöar också ner visningen av pulsräkningen ------
  lcd.setCursor(0, 1);
  lcd.print("STOP");
  delay(50);

// -- Dessa tre rader nedanför gör pipljudet när stopsensorn (ovan) täcks
tone(tonePin, 880, 125);
delay(650);
noTone(tonePin);
}


// -- Dessa 3 rader visar text när nedåtknapp trycks NED - delay ställer flimret men slöar också ner visningen av pulsräkningen ------
lcd.setCursor(0, 1);
lcd.print("Up");
delay(50);
}
}




// ---- ÅKER NER ----
else {
val = digitalRead(intest2Pin);         // NER - Läser input värde
if (val == HIGH) {                     // Checkar om knappen trycks
digitalWrite(controlPin1, LOW);       
digitalWrite(controlPin2, HIGH);

// -- Detta är sensorn som, om täcks, hindrar motorn från att åka ner
{
val = digitalRead(stopsensor1Pin);         // Sensorn som stoppar motorn
if (val == HIGH) {                     
digitalWrite(controlPin2, LOW);

// -- Dessa 3 rader visar STOP när sensorn stoppar nedgång - delay ställer flimret men slöar också ner visningen av pulsräkningen ------
  lcd.setCursor(0, 1);
  lcd.print("STOP");
  delay(50);

// -- Dessa tre rader nedanför gör pipljudet när stopsensorn (ovan) täcks
tone(tonePin, 880, 125);
delay(650);
noTone(tonePin);
}

// -- Dessa 3 rader visar DOWN när nedåtknapp trycks NED - delay ställer flimret men slöar också ner visningen av pulsräkningen ------
  lcd.setCursor(0, 1);
  lcd.print("Down");
  delay(50);
}


// -- Dessa två rader stoppar motorn när man släpper knappen
}  else 
{
digitalWrite(controlPin1, LOW);        
digitalWrite(controlPin2, LOW);       
}


}
}
}

Hold on a moment. Now that you have learned how to post images the next step is to learn how to post code.

To make it easy for people to help you please modify your post and use the code button </>

so your code looks like this

and is easy to copy to a text editor. See How to use the Forum

Your code is far too long for me to study quickly without copying to a text editor.

...R

Ok its done :slight_smile:
Sorry again!
From now on and forevermore, I'll post my pics and code in the proper way, looks much better also.

I guess i need some function to STORE the pulses/position.
But how on earth can I confirm what it has saved? To see it?
It would be good if I could view the saved position for a short while ON the screen.

Then the next thing is for the motor to halt/stop as it passes by this position it has saved.

I want to save the position, so that when the motor is going by this position again it stops.

I don't understand what position you want to save. I don't understand what defines when to determine/save the position and what defines "again". I would have a very hard time implementing this requirement.

For example. When I press one button for a short while.
The pulses is seen on a LCD, and it lands on a number when I lift my finger from the button.
Lets say 768.

Now, I want to press a button, to store this position.
Boink, the number 768 is stored in memory for UNO to later do something with.

Then, when I go by/passes this number again, 768, I want the motor to stop.
I want the UNO to know/recognize that this is the same number that is stored, 768.
And when its stopped at 768, if I want to drive the motor again in some direction, I need to lift my finger, and put the finger back on the button.

So, I need to be able to save the position, and for the motor/uno to understand what to do with this number when it again crosses the LCD and the position.

Unikron:
Then, when I go by/passes this number again, 768, I want the motor to stop.

On this occasion I think it may be helpful to start at the back.

Can you write a program that can get the motor to move 768 pulses and then stop. Just build the number 768 into your program. Worry about how to change the number later. Or maybe just use 68, so you don't have to wait so long.

...R

Ok, but how will I in a proper way do that?
To write a number to make the motor move?
Isnt there ANY examples anywhere?

Unikron:
Ok, but how will I in a proper way do that?
To write a number to make the motor move?
Isnt there ANY examples anywhere?

If you don't understand how to do that, adding the complexity of reading an encoder (which is not what you have) or any other "how many times did THAT happen" sensor does not make sense.

What kind of motor is that? It looks like a regular electric motor that you can not precisely control the position of. If it is, then your whole project is doomed.

Unikron:
Ok, but how will I in a proper way do that?
To write a number to make the motor move?
Isnt there ANY examples anywhere?

I am confused now.

You started your Original Post with

I have a quite simple program in Arduino

but now you seem to be saying that you don't know how to do the simple stuff.

To help get your started this is derived from a program I use to monitor the speed of a small DC motor using an optical detector. It is not complete but it should illustrate the idea.

volatile unsigned long isrMicros;
unsigned long latestIsrMicros;
unsigned long previousIsrMicros;
volatile boolean newISR = false;


void loop() {
   if (newISR == true) {
     previousIsrMicros = latestIsrMicros; // save the old value
     noInterrupts(); // pause interrupts while we get the new value
        latestIsrMicros = isrMicros;
        newISR = false;
     interrupts();
     microsThisRev = latestIsrMicros - previousIsrMicos;
}

void myISR() {
   isrMicros = micros();
   newISR = true;
}

You could modify it to count pulses rather than record times.

You just need to turn on your motor, start counting pulses and turn off the motor when you get to the required number - but don't stop counting the pulses because you will need to know if the motor goes too far, and by how much.

...R

Ok thanks! I'll have a look at your code and see if I get any wiser. :o

As for "Simple code", i just guessed that this should be very simple code for any experienced programmer.
As it is my first program, and its quite an miracle that it actually works as I intend it to, I myself consider it very simple compared to some i have seen people do with Arduino and code.
I would also guess that this code looks very crude and maybe wrong in an experienced programmers eyes, but at least it actually works as it should (except for the programming function wich I have not been able to add yet).

I've done a few modifications now, by ALOT of trial and error :o so this is the new stuff:
(here I also tell what I want it to do further in time).

Now it stops at position +300.
So if I press the button, and my counter comes to 300, it stops there (I could change this in the code).
And with a nice little melody to confirm it too.
It stops at this position no matter if you come from one direction or the other.
THIS is the position I'd like the code to be able to change via ONE button. And store in memory.
So that i can via a button program it, and via another button just delete this position.

I also have a sensor that work in a similar way, a sensor I can place it anywhere. And when passing it, the motor halts and cannot go by it. No matter what direction it comes from.

It now also shows on the display WHAT I am doing and what is happening, "Going up", "Going down", "Programmed stop 1" or "Down protection stop" etc.

I have now also added very short melodies for when the motor reaches its end at both directions.
A darker "warning" sound, to confirm that it reached its stop and one can release the button now and go the other direction or stay there. :slight_smile:
These are two separate commands, so one is not dependend on the other.

I am very thankful that you professionals try to help me with this. Thanks to this forum and another in my language, I am getting forward each time. And now I actually have a program that works the way I want it too, just need to add a little more functionality to it.
My head really burns sometimes when I run into these programmingproblem here.
I learn what some commands mean, and then forget when doing something else for a while etc.
I do get that it could be frustrating for you to help me also, as I'm still not used to the way programmers discuss, words used and communicate about these matters. But I'll try to keep my head on.
:slight_smile:

A medal here for you who helped me!

You're going to have to learn to use arrays. Once you have a grasp of arrays you'll have the ability to store a sequence of positions and read back those positions to control motor movement. One aspect of that is deciding how many positions you want to be able to store.

You're going to need another input to tell the processor to 'store this position' - see above.

Since you want to have the positions restored after a power-down you also need to get familiar with the EEPROM library so you can store things there and retrieve them.

This video demonstrates some of the things you'll need to do to control the motor.