Programming help for wireless control of stepper motor via rotary encoder.

Evening from Aus (1.33AM),

I would like some help on the following. I am attempting to create direct wireless stepper motor control via:

  • 28BYJ-48 stepper motor and U0003 motor controller
  • 2 x nrf24L01 2.4ghz cards
  • 1 arduino mega and 1 uno

The intention is to mount this to my super fine focus on my telescope as adjusting the focus while zoomed into Jupiter makes the image shake uncontrollably.

I have some experience with arduino before and have managed to put the hardware together, however, I am struggling with the programming side of things. After trawling the internet and other people's projects and codes, I have managed to achieve the following:

  • Transmitter to send a number based on the position of the rotary encoder
  • Receiver to receive that number. (confirmed via serial monitor)

I'm struggling to convert the series of numbers into 1 step movements for the stepper motor.

Refer attached for my code - any help would be much appreciated.

Also, if you could explain in the receiver (numbers only) code, what does this bit actually do - i.e. how does it grab a number from what is sent across?

struct package
{
int id=0;
};

byte addresses[][6] = {"0"};

Any help would be much appreciated.

Regards,

Rog.

transmitter.ino (1.18 KB)

receiver (numbers only).ino (589 Bytes)

receiver_motor.ino.ino (2.29 KB)

What rotary encoder do you have that does this: "Transmitter to send a number based on the position of the rotary encoder"?

Rotary encoders return the fact that the encoder has moved one step.

Paul

Yes, one normally needs an absolute encoder to let you know where it is, unless it is homed first to a known starting position and then moved, and the motor does not slip at all.

Examples;

https://www.digikey.com/products/en/sensors-transducers/encoders/507?k=absolute%20encoder

28BYJ-48 stepper motor has no encoder built in, so where is the position data coming from?

Your transmitter code just seems to indicate a "standard" rotary encoder is being used, with no homing, nor any reading a saved position to start from.

I also don't see the Stepper.h library called out to actually move the stepper.

I guess the TO uses the stepper-motor just to move forward / backward and a real reference is not needed.
Just turn encoder CW or CCW to create pulses on the encoder and this shall make the steppermotor move one step per pulse CW or CCW.

If it shall work this way transmitting the actual number of the variable counter is not nescessary
Then it would be enough to determine rotation-direction CW or CCW and to transmit +1 or -1

Then just receive the "+1" or the "-1" and do a step with the stepper-motor including the sign.

some encoders with mechanical switches don't count reliable when you change the rotation-direction.
What kind of rotary-encoder are you using?

Did you do tests if changing the rotation-direction is properly counting up/down your counter?

best regards Stefan

Thanks guys for the responses,

i am just using a generic rotary controller. when you start the arduino up, the code starts at zero and makes the number go up and down depending on the turns of the rotary encoder.

And yes, so if i turn it, the number goes up and down respectively based on direction.

How would i convert this to only send +1 or -1?

Cheers

Rog.

If you are only interested in +1 or -1 stepper moves, I would think that push buttons are an easier solution than an encoder.

eclectik:
Thanks guys for the responses,

i am just using a generic rotary controller. when you start the arduino up, the code starts at zero and makes the number go up and down depending on the turns of the rotary encoder.
And yes, so if i turn it, the number goes up and down respectively based on direction.

How would i convert this to only send +1 or -1?
Cheers
Rog.

I re-formatted your main-loop so that indention meets the usual standards

	if (aState != aLastState){
    // If the previous and the current state of the outputA are different, that means a Pulse has occured
	// If the outputB state is different to the outputA state, that means the encoder is rotating clockwise
      if (digitalRead(outputB) != aState) {
    	  counter ++;
	  }
	  
	  else {
		  counter --;
		  //analogWrite(en, 255);
	  }
	  Serial.print("Position: ");
	  Serial.println(counter);
	  radio.write(&counter, sizeof(counter));
	  //Serial.println("datasent"); 
    }

you add another variable lets name it

int rotationDirSnd  // Snd = sended = transmitterside

inside the code-block of the if-condition that determines CW / CCW rotation and then executes

counter ++;

or

counter --;

you add setting

rotationDirSnd = 1;

or

rotationDirSnd = -1;

and then you transmit the value of variable "rotationDirSnd"

radio.write(&rotationDirSnd, sizeof(rotationDirSnd));

the definition of the data-structure on the receiver side has to match the datastructure you send on the transmitterside.
I'm not familier with the details how this is done. Do you have any example-code that shows how datatransmission with
nrf24L01 2.4ghz cards is received by using the command

radio.read(&data, sizeof(data));

For easier maintaining your code later variable-names on both sides should match
So that just reading the names says the meaning.

inside your receiver-code

struct package
{
  int rotationDirRcv = 0; // Rcv received = receiver-side
};

I don't know if this will have the perfomance and dynamic that you you want. This depends on how fast you can create pulses on the encoder through turning it by hand. And how much steps are needed to set the focus.
If the speed is too slow a more sophisticated code is nescessary and may be a "fast mode" creating more than one step per encoder-pulse and a "slow mode" .
Switching between fast-mode and slow-mode could be done by a switch

best regards Stefan