Arduino powered gramophone project help, noob

Hi I'm attempting to recreate a gramophone with a wind up handle using an arduino and a rotary encoder and I'm already using pure data to handle the audio side of the project. I need to have it so when somebody turns the handle in a clockwise manner the record spins clockwise and when its spun anticlockwise the record responds accordingly. However I need it so the rate at which its being turned matches the speed of the record. Most of the encoder libraries/tutorials I've come across have values that go up to around 65000 when its turned anti clockwise and I'm at a loss trying to use these values when working with the motor. I'm wondering does anyone have any advice on how to use these values or whether there are any more suitable libraries out there to help me achieve what I'm trying to do?

Ours didn’t go backwards.
You could play at the crank and kind of make it do funny things like, still not the DJ tool, but it was made to wind up and then it would stay at speed, while unwinding, for a while.

In one direction you could use crank “impulses” over time to result motor speed variation over time, work out some dampening in firmware.
How would you accommodate abrupt changes from one direction to the other?

Most of the encoder libraries/tutorials I've come across have values that go up to around 65000 when its turned anti clockwise and I'm at a loss trying to use these values when working with the motor.

Not 65535, by any chance?

You're not handling signed numbers correctly. Post your code and your results.

Yes its 65535 I just didn’t have it open in front of me at the time I posted so I was unsure of the exact value. I’m working with one of the libraries I found on this site and it works perfectly my problem is that I can’t translate the larger anti clockwise values into data I can use and I’m not really sure how to as I’m new to working with the encoder and arduino in general. Ideally I’d be able to use the larger numbers but if I can’t I’m wondering if its possible to still allow for back winding but to restrict the encoder from going below the zero mark? I’m sorry if this is a stupid question but I’m really stumped here. I’ve attached code I’m using that uses software debouncing. I just have to solve this because I still have to introduce some RFID functionality to the project that allows the gramophone to differentiate between which song it has to play when certain items are place in close proximity to it.

debouncer.ino (1.73 KB)

Before you end up with several people pointing it out to you, is there a specific reason that you are trying to do this ( making the record speed/direction match the speed and direction of the crank?)

I ask, because as it was pointed out already, this is not how a grammophone normally works (I own a victrola.) In fact, running backwards would likely damage the record and possibly the reproducer (that may depend on model…it would on mine.) But perhaps you have a specific reason for doing it this way?

Sorry I should have been clearer about that earlier but basically its using a gramophone as an interface but its not going to function in the exact same manner. Its a gramophone and when a person selects an object from a selection and places it a pedestal the arduino will recognize the RFID tag inside and select a song that corresponds to the audio. Then the user will turn the hand crank which will affect the speed of the audio until its playing at a normal speed. The audio is being handled with Pure Data and Processing and I have this working already to a degree so I won't actually be damaging a record but I still want this working for the general look of the project. I also must handle the anti clockwise turning of the hand crank and this is my main problem at the moment it is working but I am unable to do anything with the values once it goes below the 0 mark to 65535.

I am unable to do anything with the values once it goes below the 0 mark to 65535.

sp. "-1"

Also, you need only two pieces of information to do what you are trying to do:

  1. Direction of rotation. That is determined by whether the A or B pulse leads as you can see in the interrupt routines in your example. But instead of counting, just set a flag called direction (for example) for something like 1=clockwise, 0 = anti-clockwise. This reduces it to just two values. Very easy to use that information to control the direction of your motor. This takes care of your direction requirement. Very simple to implement by just changing the interrupt routines:
// Interrupt on A changing state
void doEncoderA(){
  // debounce
  if ( rotating ) delay (1);  // wait a little until the bouncing is done

  // Test transition, did things really change? 
  if( digitalRead(encoderPinA) != A_set ) {  // debounce once more
    A_set = !A_set;

    // adjust counter + if A leads B
    if ( A_set && !B_set ) 
     Direction = 2;
     ticks++ //count the number of ticks

    rotating = false;  // no more debouncing until loop() hits again

// Interrupt on B changing state, same as A above
void doEncoderB(){
  if ( rotating ) delay (1);
  if( digitalRead(encoderPinB) != B_set ) {
    B_set = !B_set;
    //  adjust counter - 1 if B leads A
    if( B_set && !A_set ) 
     Direction = 1;

    rotating = false;
  1. Rate of change. Currently, the code you are using determines magnitude and position of the encoder as this is typically what you would use an encoder for. But you are wanting to essentially have a tachometer, but with direction information. The tachometer portion would only need to look at one of the encoder inputs. It doesn't really matter if it is A or B. So, look for some tachometer code to get speed information.

Essentially you would count pulses for a certain period of time, then extrapolate that into a speed. So, for example, if you counted 10 pulses over 10ms, your speed would be 100pps. If you counted 20 pulses in 10ms, it would be 200pps and so on. Really it is arbitary in your case.

The motor is only going to respond at a certain minimum analogwrite value and will max out at some value. The min and max analogwrite values are 0 to 255, but your motor will not respond to the entire range. So you need to first determine what the minimum and maximum values actually are. Then you would set your scale of speeds from the encoder to map to the range of values for the motor. No movement would equal 0, slowest movement might equal 90 (just an example) and anything from the fastest you determine and above would equal 180 (just an example)

Direction of motor is usually controlled by which input on the H-bridge is getting the PWM data (the other is set to ground.) Speed is controlled by analogWrite.

You can pretty much just make up your own ratio since it really isn't critical beyond making the speed linear. But you could get more precise by determining RPM of the encoder (you will need to know the number of ticks in one revolution, this will be in the datasheet) and the RPM of the motor at different analogWrite values (much more difficult to measure.)

For TRUE closed loop control, you would need to have something on the motor to measure RPM. Then you could use a PID loop.

I really don't think this is absolutely cricitcal in your case. Just decide whatever scale you want and map it in a linear fashion. Whether the motor is exactly 60rpm at a value of 90 AnalogWrite or 75rpm at 120 is probably not really all that important. Only that it is the same speed each time.

BTW, it is unlikely that the motor is going to provide a noticeable change in RPM for small changes of analogWrite and also unlikely that it is going to be absolutely linear (meaning a difference of 10 in value will not equal an exact difference in speed over the entire range.) So, expect a lot of tweaking to get everything to operate with the effect you desire.

Thanks a lot for the advice looks like I have plenty more to learn about the arduino :)

So, this is just electronic playback, there's no motor involved?

There is but its more for aesthetic purposes and the speed of the audio will correspond to the speed at which the motor spins the record. Its just to provide another type of feedback to the user besides the audio.

Did my information make sense? I tried to be generic.

Yes you explained it very clearly and I know now what I have to do thanks again!