LowPowerLab Forum

Hardware support => Moteino => Topic started by: Soffer on August 25, 2013, 06:54:38 AM

Title: Using 2 Moteinos with encoder and stepper
Post by: Soffer on August 25, 2013, 06:54:38 AM
Hey there.

I'm trying to adapt a code I've written for the Uno and XBee and import it to the Moteino.
The sending unit has an optical encoder that sends either "up" or "down" signals.
The receiving unit translates this into "encoder ++" or "encoder --" and than uses the AccelStepper lib to move the stepper in the right direction.

Something is wrong, and I can't for the life if me figure it out.
What happens is that the encoder values are received and change, but the motor seems to vibrate but not rotate.
I have checked the motor, the Easydriver, and the optical encoder.
I even began by simply doing a fresh start and writing a new code to test a Moteino unit with encoder and stepper attached to it.
It worked just fine.

I'd really appreciate if someone could have a look at this code and tell me what's wrong.
Thank you.
////////////////////////
//Moteino FF Receiver///
////////////////////////

#include <RFM12B.h>
#include <AccelStepper.h>
#include <avr/sleep.h>


//int for radio data
int a;
int sum;

//encoder/motor/driver setup
int easyDriverMicroSteps = 4;
int rotaryEncoderSteps = 75;
int motorStepsPerRev = 200;

int MinPulseWidth = 50; //too low and the motor will stall, too high and it will slow it down

int easyDriverStepPin = 8;
int easyDriverDirPin = 9;
int enablePin = 10;

volatile long encoderValue = 0;
byte dataReceive = 0;
long lastencoderValue = 0;

//ON LED
#define onLed 12

AccelStepper stepper(1, easyDriverStepPin, easyDriverDirPin);

//Sleep Function - to diable ED when not active
long previousMillis = 0;
int sleepTimer = 5000;

// You will need to initialize the radio by telling it what ID it has and what network it's on
// The NodeID takes values from 1-127, 0 is reserved for sending broadcast messages (send to all nodes)
// The Network ID takes values from 0-255
// By default the SPI-SS line used is D10 on Atmega328. You can change it by calling .SetCS(pin) where pin can be {8,9,10}
#define NODEID        1  //network ID used for this unit
#define NETWORKID     99  //the network ID we are on
#define GATEWAYID     2  //the node ID we're sending to
#define SERIAL_BAUD 115200

//encryption is OPTIONAL
//to enable encryption you will need to:
// - provide a 16-byte encryption KEY (same on all nodes that talk encrypted)
// - to call .Encrypt(KEY) to start encrypting
// - to stop encrypting call .Encrypt(NULL)
uint8_t KEY[] = "ABCDABCDABCDABCD";

// Need an instance of the Radio Module
RFM12B radio;
byte sendSize=0;
char payload[] = "1234567890";
bool requestACK=false;


void setup()
{
  radio.Initialize(NODEID, RF12_433MHZ, NETWORKID);
  radio.Encrypt(KEY);      //comment this out to disable encryption
  Serial.begin(SERIAL_BAUD);
  Serial.println("Listening...");

  stepper.setMinPulseWidth(MinPulseWidth);
  stepper.setMaxSpeed(50000);             //variable to later determine speed play/rewind
  stepper.setAcceleration(1000000000);
  stepper.setSpeed(50000);

  pinMode(enablePin, OUTPUT);
}

void loop()
{

  if(encoderValue != lastencoderValue)
  {
    digitalWrite (enablePin, LOW);
    stepper.run();
    int stepsPerRotaryStep = (motorStepsPerRev * easyDriverMicroSteps) / rotaryEncoderSteps;
    stepper.moveTo(encoderValue * stepsPerRotaryStep);
    lastencoderValue = encoderValue;
    previousMillis = millis();
  }
  else
  {
    //Stepper sleep after 5sec of no data
    unsigned long currentMillis = millis ();
    if (currentMillis - previousMillis>sleepTimer)
      digitalWrite (enablePin, HIGH);
  }

  if (radio.ReceiveComplete())
  {
    if (radio.CRCPass())
    {
      sum = 0;
      for (byte i = 0; i < radio.GetDataLen(); i++) //can also use radio.GetDataLen() if you don't like pointers
      {
        a = (radio.Data[i]);
        sum+=a;
      }
      Serial.println(sum);
      if (sum == 49)
      {
        encoderValue++;
        Serial.println(encoderValue);
      }
      else if (sum == 99)
      {
        encoderValue--;
        Serial.println(encoderValue);
      }
    }
  }
}
Title: Re: Using 2 Moteinos with encoder and stepper
Post by: Soffer on August 25, 2013, 11:05:55 AM
I think my problem is here somewhere -
if (radio.CRCPass())
    {
      sum = 0;
      for (byte i = 0; i < radio.GetDataLen(); i++) //can also use radio.GetDataLen() if you don't like pointers
      {
        a = (radio.Data[i]);
        sum+=a;
      }
      Serial.print("sum: ");
      Serial.println(sum);
      if (sum == 49)
      {
        encoderValue++;


The way I'm trying to sum up the data isn't right but I don't really know what it is I'm messing up there.
Title: Re: Using 2 Moteinos with encoder and stepper
Post by: Soffer on August 25, 2013, 12:16:03 PM
Or maybe something with the pins I don't get?
Title: Re: Using 2 Moteinos with encoder and stepper
Post by: Soffer on August 26, 2013, 05:14:46 AM
OK, I'm really going crazy here trying to figure out what's going on -
The thing that's really weird is that as long as the LED is on - the values go up
and then the LED goes off (for no apparent reason) and the values go down.
What is going on here?
Please help!
Title: Re: Using 2 Moteinos with encoder and stepper
Post by: Soffer on August 26, 2013, 05:50:04 AM
issue no1 resolved: pin d10 is a problem when using radio...
moving on...
Title: Re: Using 2 Moteinos with encoder and stepper
Post by: Felix on August 26, 2013, 08:15:44 AM
Yes, pins 2, 10-13 are offlimits when using the radio.
Also, you're getting back bytes, which can be casted to chars if thats what you passed on the other side. Without the send sketch I'm not sure why you are summing up and what 49 and 99 means.
Title: Re: Using 2 Moteinos with encoder and stepper
Post by: Soffer on August 26, 2013, 02:22:13 PM
Thanks Felix.
I'm summing things up as a way to categorize all the functions that are yet to be written into both the sending and receiving ends.
This is the only way I figured to do this:
Every function I write sends the data load + 1. This means that "up" sends out "1" "down" sends out "12" and so on.
Because using encoder means continuous data (i.e. "down" will send "12" and "12" and so on) I had to find a way to sum
the data. And so I'm summing it from char to dec.
It's probably a very primitive solution but this all data transferring method isn't easy for me - I'm used to XBee which has a kind of "simpled down" mode for novices in the communications protocols...

Any way, this is the working code.
I hope soon to finish this process of transferring my project to your platform, and I'd be delighted to showcase it here.
You can check the Uno/XBee version over at my blog: http://adisoffer.tumblr.com/post/25422476290/you-read-the-post-now-watch-the-movie-arduino-follow (http://adisoffer.tumblr.com/post/25422476290/you-read-the-post-now-watch-the-movie-arduino-follow)
:-)

////////////////////////
//Moteino FF Receiver///
////////////////////////

#include <RFM12B.h>
#include <AccelStepper.h>
#include <avr/sleep.h>


//int for radio data
int a;
int sum;

//encoder/motor/driver setup
int easyDriverMicroSteps = 4;
int rotaryEncoderSteps = 75;
int motorStepsPerRev = 200;

int MinPulseWidth = 50; //too low and the motor will stall, too high and it will slow it down

int easyDriverStepPin = 15;
int easyDriverDirPin = 16;
int enablePin = 17;

volatile long encoderValue = 0;
byte dataReceive = 0;
long lastencoderValue = 0;

//ON LED
#define onLed 12

AccelStepper stepper(1, easyDriverStepPin, easyDriverDirPin);

//Sleep Function - to diable ED when not active
long previousMillis = 0;
int sleepTimer = 5000;

// You will need to initialize the radio by telling it what ID it has and what network it's on
// The NodeID takes values from 1-127, 0 is reserved for sending broadcast messages (send to all nodes)
// The Network ID takes values from 0-255
// By default the SPI-SS line used is D10 on Atmega328. You can change it by calling .SetCS(pin) where pin can be {8,9,10}
#define NODEID        1  //network ID used for this unit
#define NETWORKID     99  //the network ID we are on
#define GATEWAYID     2  //the node ID we're sending to
#define SERIAL_BAUD 115200

//encryption is OPTIONAL
//to enable encryption you will need to:
// - provide a 16-byte encryption KEY (same on all nodes that talk encrypted)
// - to call .Encrypt(KEY) to start encrypting
// - to stop encrypting call .Encrypt(NULL)
uint8_t KEY[] = "ABCDABCDABCDABCD";

// Need an instance of the Radio Module
RFM12B radio;
byte sendSize=0;
char payload[] = "1234567890";
bool requestACK=false;


void setup()
{
  radio.Initialize(NODEID, RF12_433MHZ, NETWORKID);
  radio.Encrypt(KEY);      //comment this out to disable encryption
  Serial.begin(SERIAL_BAUD);
  Serial.println("Listening...");

  stepper.setMinPulseWidth(MinPulseWidth);
  stepper.setMaxSpeed(50000);             //variable to later determine speed play/rewind
  stepper.setAcceleration(1000000000);
  stepper.setSpeed(50000);

  pinMode(enablePin, OUTPUT);
}

void loop()
{
  int stepsPerRotaryStep = (motorStepsPerRev * easyDriverMicroSteps) / rotaryEncoderSteps;
  stepper.moveTo(encoderValue * stepsPerRotaryStep);
  stepper.run();

  if(encoderValue != lastencoderValue)
  {
    lastencoderValue = encoderValue;
    digitalWrite (enablePin, LOW);
    previousMillis = millis();
  }
  else
  {
    //Stepper sleep after 5sec of no data
    unsigned long currentMillis = millis ();
    if (currentMillis - previousMillis>sleepTimer)
      digitalWrite (enablePin, HIGH);
  }

  if (radio.ReceiveComplete())
  {
    if (radio.CRCPass())
    {
      sum = 0;
      for (byte i = 0; i < radio.GetDataLen(); i++) //can also use radio.GetDataLen() if you don't like pointers
      {
        a = (radio.Data[i]);
      }
      sum+=a;
      Serial.print("sum: ");
      Serial.println(sum);
      if (sum == 49)
      {
        encoderValue++;
      }
      else if (sum == 50)
      {
        encoderValue--;
      }
    }
  }
}

Title: Re: Using 2 Moteinos with encoder and stepper
Post by: Felix on August 26, 2013, 03:07:40 PM
Cool video!
Hey - did you see the post about using structs instead of clear text?
Maybe structs are a more lean way for you to pass your data... just an idea..

http://lowpowerlab.com/forum/index.php/topic,94.0.html
Title: Re: Using 2 Moteinos with encoder and stepper
Post by: Soffer on August 28, 2013, 10:25:02 AM
Thanks  :)
will check link, hope to update soon...