Turns Counter Project (Newbie)

Hello everyone,
I am fairly new to working with Arduino, and have decided to take on a project that i will most likely need a lot of help with (IN CODING) if anybody is interested. I am looking for guidance, not direct answers for the most part please :smiley: .
(P.S. Is there any way to create a thread for my project so that there are threads within threads for each step i need help with?)

The project:
replace an older coil winding machine's mechanical turn counter with an electrical setup.

First problem:
i need help changing the value that serialPrint places in the serial monitor. (if this is even the way to go about doing it).

I am using an quadrature encoder that is 1024 p/r.

I need the value in the serial monitor to raise only one place for every 204.8 pulses. (the ratio on my mechanical counter is 20:1) How do i go about understanding how to divide a variable in the program, and where to place that line of code.

So... Can somebody please explain how i would edit the attached simple code to make an encoder print a 1 for every say... 4 pulses? and vise versa, say it pulsed 4 times for every one tick, how to make is read as just 1?

Thanks.

Here is my code

Basic.pde (741 Bytes)

There is no facility for Threads within Threads and it is probably easier if you keep all of the info in a single Thread so that everyone can see all of it easily.

Does the code you posted work with the encoder you have. What does it print out?

I'm guessing that it shows the position incrementing as the encoder is turned - but I may be wrong.

You could try a few new lines like this

    oldPosition = newPosition;
            long divCount = newPosition / 4;   // <--- new
            Serial.print(divCount);   // <--- new
            Serial.print("    ");   // <--- new
    Serial.println(newPosition);

...R

Thanks for the help,

so, i am gathering that the code is using "long" before variables to tell the arduino that the encoder's value will be very high. Is this correct?

Here is the section of code i have written thanks to your guidance.

#include <Encoder.h>
// Change these two numbers to the pins connected to your encoder.
//   Best Performance: both pins have interrupt capability
//   Good Performance: only the first pin has interrupt capability
//   Low Performance:  neither pin has interrupt capability
Encoder myEnc(2, 3);
//   avoid using pins with LEDs attached
int BUZZ = 12; // set pin 12 to buzzer
int numberOfTurns = 100; // set the desired number of turns
void setup() {
  pinMode (BUZZ,OUTPUT); // set my buzzer pin as output
  Serial.begin(9600); // set baud rate
  Serial.println("Coil Turn Counter"); // printing title in serial print
  
}

long oldPosition  = -999; // i dont know what this does

void loop() {
  long newPosition = myEnc.read(); // read  from enc library and establish it is a long number
  long x = newPosition / 204.8; // set my 20 to 1 ratio for encoder
  if (newPosition != oldPosition){ // this is to print it once and determine value
    oldPosition = newPosition;
    Serial.println(numberOfTurns - x); // prints x value to count down to
  }
  if (numberOfTurns - x <= 0) { // sets the buzzer to go at countdown to zero
    digitalWrite(BUZZ,HIGH);
  } else { digitalWrite (BUZZ,LOW);
  }
}

Since the top of the encoder code is referencing a library, with the arduino function as normal if it is just hooked up to power and not the computer? when you reset it will it just fail to find the proper info? Also can you explain the "long old position = -999" line to me?

Thanks,

encoder_1-20_ratio_code.ino (1.17 KB)

The Arduino uses 3 sizes of integers - char, int and long which are respectively 8, 16 and 32 bits in size.
all of these allow for positive and negative values. long is used to allow for the possibility of large numbers - the max will be 2 **31 (the other bit is for the sign).

the line oldPosition = -999 is just to facilitate the first test of if (newPosition != oldPosition) as it should be impossible for the first value of newPosition to be -999.

This line won't work - long x = newPosition / 204.8; because you are trying to mix integer and floating point maths. I suggest for testing that you just divide by 204 until you are satisfied that you are getting sensible numbers. You will have to convert all the values into float to do floating point maths. However you will probably lose precision which may cause a problem with your application. Perhaps 204.8 can be represented as an integer calculation - for example newPosition * 10 / 2048. But you still need to be careful that the maths works properly. For example what result would you expect if newPosiition was 387 ?

Where does the strange number 204.8 come from?

...R

i got the number 204.8 because my encoder is a quadrature encoder with 1024 ppr. I get 4096 ppr. The coil winding machine ratio is 20:1, hence the 204.8 number.

Can i ask why the "long x = newPosition / 204.8;" wont work? I compiles fine and i have tested it with my encoder and it seems to work just fine. Is there an underlying problem that i need to research that will come to bite me in the end? My turns on the encoder come out to exactly 20 counts per 1 revolution.
(it does however print numerous number replicas until the desired position is reached... 1 1 1 1 1 1 1 2.)

Whenever i change the -999 to -99 it messes up my readings. If it is just testing the first if statement then why does it do this?

Thanks again for the help

Can i ask why the "long x = newPosition / 204.8;" wont work?

Because the compiler sees it as "long x = newPosition / 204;"?

I need the value in the serial monitor to raise only one place for every 204.8 pulses. (the ratio on my mechanical counter is 20:1)

My turns on the encoder come out to exactly 20 counts per 1 revolution.

I'm not understanding your mechanical set up? Is the encoder on the motor shaft? Is there a gear ratio between the motor and the winding spindle? Where does the 20/1 ratio on the mechanical counter come from?

Depending upon your system, the encoder may not be the best way to go to count turns, and you might do better to change course and use a hall sensor and magnet, or an optical sensor and a reflective stripe, to count only pulse per revolution of the actual winding mechanism and not be reading the motor revolutions.

AWOL:
Because the compiler sees it as "long x = newPosition / 204;"?

Actually, the compiler will do the following:

long x = (long)(((float)newPosition) / 204.8);

newPosition will be promoted (converted) to a float, divided by 204.8 using floating point division, and the result of the division will then be converted back to a long.

Though one could argue about the stylistic "correctness" of the syntax, it will give him the result he wants, as it will do the scaling using the full precision of float, then round the result to a long, which is as accurate as he is going to get.

Regards,
Ray L.

The next issue that i am having is to control a variable thru an LCD menu.

I am trying to achieve a display that says "Number Of Turns" and below that is a digit editable number which is linked to my "number of turns" variable in the code.

Can somebody please guide me in the right direction for this? Is there an example code i can fiddle with?

Thanks

As Cattledog alludes to, I think that without that complication, this becomes a nice, easy, fun project for you. - Scotty