Loading...
  Show Posts
Pages: 1 2 [3] 4 5 ... 11
31  Using Arduino / Networking, Protocols, and Devices / Xbees not playing nice with eachother on: September 17, 2012, 09:11:21 am
Would appreciate some knowledgeable advice here.
MY project consists of a "Sender" arduino (nano) carrying a S1 xbee, and a "Receiver" arduino (Uno) carrying S1 as well.
Most of the data traffic is nano ->uno, but in 2 specific cases on the receiver code (Rewind and Play cases) I need to send back a confirmation to the sender and make it turn an LED down. Now the thing is, it sometimes works and sometimes doesn't and I can't see any logic to this. Maybe I'm overflowing the Xbee modules? Maybe I'm doing some basic thing all wrong?
Really need some help here and attaching the codes.

Sender:
Code:
#include <OneButton.h>

// Movement of Optical encoder is translated to moving stepper
//



//these pins can not be changed 2/3 are special pins
int encoderPin1 = 2;
int encoderPin2 = 3;

int lastEncoded = 0;
int encoderValue = 0;

int lastencoderValue = 0;
int lastMSB = LOW;
int lastLSB = LOW;

//LEDs
#define realTimeLED 12      //Real Time LED
#define playLED 9          //PLay LED
#define inLED 11            //In LED
#define outLED 10           //Out LED

// Setup OneButton
OneButton realTimebutton(A4, true);
OneButton playButton (A1, true);
OneButton inButton (A3, true);
OneButton outButton (A2, true);

//Values for focus points
volatile int inPoint = 0;
volatile int outPoint = 3000;

//Values for calibrating lens and motor
int lowEnd = 0;
int highEnd = 3000;

//Blink without delay
int ledState = LOW;
long previousMillis = 0;
int ledInterval = 75;

boolean rClickedOnce = false;
boolean rLongPress = false;
boolean pClickedOnce = false;

//Value for sendFunction - to send over Xbee
int value;

//value for variable speed - to send over Xbee
int valToRemap;
int encoderValToRemap;

//Value to recieve from 2nd Xbee: when "play" or "rewind" has finished"
int dataReceive;

//Modes
int mode;
#define RealTime 1
#define Stop 2
#define REWIND 3
#define PLAY 4
#define LENSCALIB 5


void setup(){
  Serial.begin(115200);

  //Pinmodes
  pinMode (realTimeLED, OUTPUT);
  pinMode (playLED, OUTPUT);
  pinMode (inLED, OUTPUT);
  pinMode (outLED, OUTPUT);
  pinMode(encoderPin1, INPUT);
  pinMode(encoderPin2, INPUT);

  digitalWrite(encoderPin1, HIGH); //turn pullup resistor on
  digitalWrite(encoderPin2, HIGH); //turn pullup resistor on

  //call updateEncoder() when any high/low changed seen
  //on interrupt 0 (pin 2), or interrupt 1 (pin 3)
  //attachInterrupt(0, updateEncoder, CHANGE);
  //attachInterrupt(1, updateEncoder, CHANGE);

  //Attach Click to Buttons
  realTimebutton.attachClick(Click);
  playButton.attachClick(ClickPlay);
  inButton.attachClick(ClickIn);
  outButton.attachClick(ClickOut);

  //Attach Press to Real Time for calibrating lens and motor
  realTimebutton.attachPress(rPress);

}

void loop(){
  
  int MSB = digitalRead(encoderPin1); //MSB = most significant bit
  int LSB = digitalRead(encoderPin2); //LSB = least significant bit
  
  //only if changed value
  if(lastMSB != MSB || lastLSB != LSB){
    updateEncoder(MSB, LSB);
  }
    
  // keep watching the push buttons:
  realTimebutton.tick();
  playButton.tick();
  inButton.tick();
  outButton.tick();

  //This was meant in order to signal "sender" arduino when the action
  //on other side (play/rewind) is done. Currently does not work
  if (Serial.available())
  {
    dataReceive = Serial.read();
    if (dataReceive == 1)
    {
      pClickedOnce = false;
      digitalWrite(playLED, LOW);
    }  
  }
}


void updateEncoder(int MSB, int LSB){
  lastMSB = MSB;
  lastLSB = LSB;
  

  int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number
  int sum  = (lastEncoded << 2) | encoded; //adding it to the previous encoded value

  if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011)
  {
    encoderValue ++;
   /* if (encoderValue>highEnd)
      encoderValue = highEnd;*/
      //Serial.println(encoderValue);
    // This is a function so as to be able to to use the data
    // in 2 different ways: 1/as encoder value
    // 2/as speed value for play/rewind
    // depending on state of switches.
    sendFunction (1);

  }
  if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000)
  {
    encoderValue --;
    /*if (encoderValue<lowEnd)
      encoderValue = lowEnd;*/
      //Serial.println(encoderValue);

    // This is a function so as to be able to to use the data
    // in 2 different ways: 1/as encoder value
    // 2/as speed value for play/rewind
    // depending on state of switches.
    sendFunction(2);
  }

  lastEncoded = encoded; //store this value for next time

}


//4 Buttons Click Functions
void Click() {
  digitalWrite(playLED, LOW);
  if (rClickedOnce == false )
  {
    rClickedOnce = true;
    digitalWrite(realTimeLED, HIGH);
  }
  else
  {
    digitalWrite(realTimeLED, LOW);
    rClickedOnce = false;
  }
}

void ClickPlay () {
  //terminate realtime in case it wasn't stopped
  if (pClickedOnce == false)
  {
    pClickedOnce = true;
    rClickedOnce = false;  
    digitalWrite(realTimeLED, LOW);
    digitalWrite(playLED, HIGH);
    Serial.write(4);
  }
  else
  {
    pClickedOnce = false;
    digitalWrite(playLED, LOW);
  }
}

void ClickIn () {
  // Saving In
  if (rClickedOnce == true)                      
  {
    Serial.write (3);
    inPoint = encoderValue;
    //Serial.println (inPoint);  
    blinkMark (inLED);
  }
  //Saving Low End of encoderVal
  // else if (rLongPress == true) {
  // lowEnd = encoderValue;
  //Serial.print ("lowEnd = ");
  //Serial.println (lowEnd);
  //}
  //blinkMark (inLED);
}

void ClickOut() {
  //Saving Out
  if (rClickedOnce == true)
  {
    Serial.write (5);
    outPoint = encoderValue;
    //Serial.println (outPoint);  
    blinkMark (outLED);
  }  

  /*outPoint = stepper.currentPosition();
   encoderOut = encoderValue;          //saved for variable speed
   Serial.print ("Out Point = ");
   Serial.println (encoderOut);
  
   else if (rLongPress ==true) {
   highEnd = encoderValue;
   Serial.print ("highEnd = ");
   Serial.println (highEnd);
   }
   blinkMark (outLED);*/
}

// Press Function - calibrating lens and stepper
// not tried yet.
void rPress() {
  if (rLongPress == false) {
    Serial.println ("Lens Limit");
    rLongPress = true;
    highEnd = 4000;
    lowEnd = 0;
    mode = LENSCALIB;
  }
  else {
    mode = Stop;
  }
}

int blinkFunction (int y)   // Blink without delay
{

  unsigned long currentMillis = millis ();
  if (currentMillis - previousMillis>ledInterval)
  {
    previousMillis = currentMillis;
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;
    digitalWrite (y, ledState);
  }
}

int blinkMark (int y)
{
  boolean b = HIGH;
  for (int i=0;i<6;i++)
  {
    digitalWrite(y, b);
    delay(75);
    b=!b;
  }
}

int sendFunction(int value)
{
  // 1/Send encoder value to move stepper
  if (rClickedOnce == true)
    Serial.write (value);

  else if (pClickedOnce == false)
    {
    // 2/Send remapped value to change speed of stepper    
   encoderValToRemap = encoderValue;
  
   if (inPoint<outPoint)
      {
      if (encoderValToRemap< inPoint)
        encoderValToRemap = inPoint;

      if (encoderValToRemap>outPoint)
        encoderValToRemap = outPoint;    
      }
    else
      {
   if (encoderValToRemap>inPoint)
     encoderValToRemap = inPoint;
    
   if (encoderValToRemap<outPoint)
     encoderValToRemap = outPoint;
      }
   //Serial.println (encoderValToRemap);
    
  
    //remap value to ba able to send bytes
    valToRemap = focusSpeed(encoderValToRemap);
    }
}

int focusSpeed (int valToRemap)
{
  //remapped value sent to "receiving" arduino to change stepper speed
  //during play/rewind.
  // currently after some revolutions of encoder Xbees stop communicating until reset.
  valToRemap = map(valToRemap, inPoint, outPoint, 10, 30);
  //Serial.print ("valToRemap");
  //Serial.println (valToRemap);
  Serial.write (valToRemap);
}

32  Using Arduino / Programming Questions / Re: A very simple Xbee test - fail? on: September 16, 2012, 09:03:37 am
Oh man - thank you peter - actually it was a lot simpler - I had missed a hole in my breadboard!!!
The fact that you asked had me going over the pins and I saw this silly mistake.
THANK YOU!
33  Using Arduino / Programming Questions / Re: A very simple Xbee test - fail? on: September 16, 2012, 08:13:46 am
Is it possible that I need API in order to accomplish this?
Anyone here with experience?
34  Using Arduino / Programming Questions / A very simple Xbee test - fail? on: September 16, 2012, 05:42:44 am
I'm trying to figure out to how send data both ways and writing this small test I can see something's wrong.
I'm probably missing some basic info here and would appreciate your help.

The Sending Arduino (nano) attached to S1 Xbee, sending values from 1 - 70 every 1500ms.
The receiving Arduino (Uno) attached to S1 Xbee, receives that data and acts accordingly. i.e changes the LED state every 10 data values, and sends back data (2) to the Nano. Now, I can see that the Nano's Xbee receives (the RSSI LED lights up every 10 data values), but action is not taken for some reason. I'm trying to differentiate between any data received and specific data - therefore only upon the receiving of (2) the Nano needs to act - but fails to.

What am I doing wrong here?

Sender Code:
Code:
//Xbee Send and Receive test - Sender.
//Meant to receive back every 10 and change LED state.

long currentMillis=0;
long previousMillis = 0;
int delayMillis = 1500;
int x=0;
int y = 0;
int LED = 13;
boolean ledState = HIGH;

void setup ()
{
  Serial.begin (115200);
  pinMode (LED, OUTPUT);
  digitalWrite(LED, HIGH);
}

void loop ()
{
  currentMillis = millis();
  if (Serial.available()>0)
  {
    y = Serial.read();
    if (y == 2)
    {
      ledState = !ledState;
      digitalWrite (LED, ledState);
    }
  }
  if (currentMillis - previousMillis>delayMillis)
  {
    x++;
    if (x>70)
      x = 0;

    Serial.write (x);
    //Serial.print (x);
    previousMillis = currentMillis;
  }
}


Receiver code:
Code:
// Xbee Send and Receive test - Receiver.
// Meant to send back every 10.

int x = 0;
int LED = 13;
boolean ledState = HIGH;


void setup ()
{
  Serial.begin (115200);
  pinMode (LED, OUTPUT);
  digitalWrite(LED, HIGH);
}

void loop ()
{
  if (Serial.available())
  {
    x = Serial.read();  
    if(x == 10||x == 20||x == 30||x == 40 ||x == 50 || x == 60||x == 70)
    {
      ledState = !ledState;
      digitalWrite (LED, ledState);
      Serial.write (2);  
    }  
  }    
}


Another weird thing that may or may not point to a problem is that upon opening the sender's serial monitor, I get this after a few seconds: " !"#$%&'()*+,-./012345678 " and so on...
35  Using Arduino / Programming Questions / Re: sending 2 bytes over Xbee on: September 11, 2012, 12:53:30 am
Just to update you guys, and point to the solution in case someone needs it -
It's much simpler, and it's got nothing to do with the interrupts (at least not in the simple sense).
The thing is the stepper.run() function which had to move outside of the if loop - this way the stepper is constantly updated.

So instead of
Code:
void loop () {
 if (Serial.available())
  {
    dataReceive = Serial.read();
    if (dataReceive == 1)
      encoderValue ++;
    else if (dataReceive == 2)
      encoderValue --;
     
  int stepsPerRotaryStep = (motorStepsPerRev * easyDriverMicroSteps) / rotaryEncoderSteps;
  stepper.moveTo(encoderValue * stepsPerRotaryStep);
  stepper.run();
}
  }

It's
Code:
void loop(){
  stepper.run();
  if (Serial.available())
  {
    dataReceive = Serial.read();
    if (dataReceive == 1)
      encoderValue ++;
    else if (dataReceive == 2)
      encoderValue --;
   
  int stepsPerRotaryStep = (motorStepsPerRev * easyDriverMicroSteps) / rotaryEncoderSteps;
  stepper.moveTo(encoderValue * stepsPerRotaryStep);
   }
}

Hope this'll help others.  smiley
36  Using Arduino / Programming Questions / Re: sending 2 bytes over Xbee on: September 09, 2012, 01:48:05 pm
Ok, think I got your meaning.
Thank you very much.
37  Using Arduino / Programming Questions / Re: sending 2 bytes over Xbee on: September 09, 2012, 01:30:31 pm
Ok, so my option here is to use the optical encoder w/o interrupts (is that possible?) thus enabling Serial.write()?
Or is there anything else I can do to read from encoder and sent the data via Xbee?
(thank you once again - this is new stuff to me and very interesting)
38  Using Arduino / Programming Questions / Re: sending 2 bytes over Xbee on: September 09, 2012, 11:58:33 am
You are correct of course but this is due to some testing and not the values in my sketch - I mistakenly left it there -  -  -  smiley-red

Same goes for the difference in ED microsteps - the value is defined as 1 after much tests to have a good response "feel" to it.

What does "you can't do Serial I/O in an ISR" mean?
Serial IO is obvious, unlike "ISR"...
39  Using Arduino / Programming Questions / Re: sending 2 bytes over Xbee on: September 09, 2012, 06:18:43 am
PaulS, any chance of you looking at this?
Thanks.
40  Using Arduino / Programming Questions / Re: sending 2 bytes over Xbee on: September 06, 2012, 02:09:29 pm
Back again with some questions  smiley

I've worked on the basic code and have split it into 2 sides - Send and Receive.
In the Send code I've intentionally left the motor related code to make sure It's working as intended -I double check myself by going wireless and wired.

2 things are wrong though:
1. The ratio between the encoder and stepper seem to have changed when going wireless - less stepper rotation in relation to same encoder rotation.
2. Stepped direction is not changing even when encoder value goes back...

What am I missing here?

Sender Code:
Code:
// Movement of Optical encoder is translated to moving stepper


#include <AccelStepper.h>

//encoder/motor/driver setup
int easyDriverMicroSteps = 4; //I think this is 4 or 8
int rotaryEncoderSteps = 75; //setps per rev on your encoder
int motorStepsPerRev = 200; //this is right  - steps per rev on the motor

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

//these pins can not be changed 2/3 are special pins
int encoderPin1 = 2;
int encoderPin2 = 3;

int easyDriverStepPin = 4;
int easyDriverDirPin = 5;

volatile int lastEncoded = 0;
volatile long encoderValue = 0;

long lastencoderValue = 0;
int lastMSB = 0;
int lastLSB = 0;

//1 means we are using a motor driver with the library
AccelStepper stepper(1, easyDriverStepPin, easyDriverDirPin);


void setup(){
  Serial.begin(115200);

  stepper.setMinPulseWidth(MinPulseWidth); //may need to play with this, but I think this is good.
  stepper.setMaxSpeed(50000);
  stepper.setAcceleration(1000000000); //try 100, or 1000 and see if it works
  stepper.setSpeed(50000); //play with this to see if it makes a diff (1 to 1000)


  pinMode(encoderPin1, INPUT);
  pinMode(encoderPin2, INPUT);

  digitalWrite(encoderPin1, HIGH); //turn pullup resistor on
  digitalWrite(encoderPin2, HIGH); //turn pullup resistor on

  //call updateEncoder() when any high/low changed seen
  //on interrupt 0 (pin 2), or interrupt 1 (pin 3)
  attachInterrupt(0, updateEncoder, CHANGE);
  attachInterrupt(1, updateEncoder, CHANGE);
}



void loop(){
  //go to where the encoder was turned to.
  int stepsPerRotaryStep = (motorStepsPerRev * easyDriverMicroSteps) / rotaryEncoderSteps;
  stepper.moveTo(encoderValue * stepsPerRotaryStep);
  stepper.run();
 
}


void updateEncoder(){
  int MSB = digitalRead(encoderPin1); //MSB = most significant bit
  int LSB = digitalRead(encoderPin2); //LSB = least significant bit

  int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number
  int sum  = (lastEncoded << 2) | encoded; //adding it to the previous encoded value

  if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011)
   {
    encoderValue ++;
    Serial.write(1);
   }
  if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000)
    {
    encoderValue --;
    Serial.write (2);
    }

  lastEncoded = encoded; //store this value for next time
  //Serial.println(encoderValue);
}


Receiver Code
Code:
// Movement of Optical encoder is translated to moving stepper


#include <AccelStepper.h>

//encoder/motor/driver setup
int easyDriverMicroSteps = 8; //I think this is 4 or 8
int rotaryEncoderSteps = 75; //setps per rev on your encoder
int motorStepsPerRev = 200; //this is right  - steps per rev on the motor

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

int easyDriverStepPin = 4;
int easyDriverDirPin = 5;
int enablePin = 6;

volatile int lastEncoded = 0;
volatile long encoderValue = 0;
int dataReceive = 0;
long lastencoderValue = 0;


//1 means we are using a motor driver with the library
AccelStepper stepper(1, easyDriverStepPin, easyDriverDirPin);


void setup(){
  Serial.begin(115200);

  stepper.setMinPulseWidth(MinPulseWidth); //may need to play with this, but I think this is good.
  stepper.setMaxSpeed(50000);
  stepper.setAcceleration(1000000000); //try 100, or 1000 and see if it works
  stepper.setSpeed(50000); //play with this to see if it makes a diff (1 to 1000)
 
  pinMode(enablePin, OUTPUT);
 }

void loop(){
  //go to where the encoder was turned to.
  if (Serial.available())
  {
    dataReceive = Serial.read();
    if (dataReceive == 1)
      encoderValue ++;
    else if (dataReceive == 2)
      encoderValue --;
     
 
  int stepsPerRotaryStep = (motorStepsPerRev * easyDriverMicroSteps) / rotaryEncoderSteps;
  stepper.moveTo(encoderValue * stepsPerRotaryStep);
  stepper.run();
  }
}

41  Using Arduino / Programming Questions / Re: sending 2 bytes over Xbee on: September 06, 2012, 08:28:49 am
Quote
I think, then, that sending an int is the wrong thing to be doing. It seems that the encoder end needs to send a "I saw a step happen" message that the stepper end receives, to know when to step again. That could be encoded in a byte, instead of an int.
This indeed seems a smarter solution.
Thanks - I'll try and work this out.
42  Using Arduino / Programming Questions / Re: sending 2 bytes over Xbee on: September 05, 2012, 01:56:11 pm
Hey PaulS - thanks.
Since this is way over my head and I will take my time figuring out what you meant, I'll just ask for one clarification: Will this method you propose allow the continuous flow of data from encoder to stepper? Meaning - since the whole set up is meant to enable the synced control of an encoder over the position a stepper I cannot send "packets" of value changes and than wait. The "wired" version of the project moves a camera lens in sync with the encoder.
(Please remember I'm a novice at this so if my question indicates I understood you poorly try and be patient... smiley-sad-blue)   
43  Using Arduino / Programming Questions / sending 2 bytes over Xbee on: September 05, 2012, 01:06:22 pm
Hey - my question is this:
I'm trying to pass along data from an optical encoder (on a "sender" arduino + Xbee S1) to a stepper motor (connected to a "receiver" arduino + Xbee S1). The data is of course an int which I guess I have to break down into 2 bytes in order to be able to send continually over the Xbees. Only problem is that I can't figure out how to do that and keep the order of 1st byte and 2nd byte. I've been doing some tests with a friend who's much more experienced at this but still it seems to be a problem. I would very much appreciate you thoughts and tips.
Here are the test codes:
Sender:
Code:
void setup(){
  Serial.begin(38400);
}

void loop() {
  int someValue = random(0, 32767);
 
  outputBytes("P", someValue);
}



void outputBytes(char* header, int value){
  //translate the value into a header + 2 data bytes
  //Works for numbers upto 32767 / -32767
  //this way we know that the value is always exactly 6 bytes
  //makes it much easier to receive on the other end
  int MSB;
  int LSB;

  MSB = value >> 8; //get just the first byte
  LSB = value & 0b0000000011111111; //get just the second byte

  Serial.print(header);
  Serial.write(MSB);
  Serial.write(LSB);
  Serial.write(LSB);
  Serial.write(MSB);
  Serial.print(header);
}

And receiver:
Code:
void setup(){
  Serial.begin(38400);
}

void loop() {
 
  while(Serial.available() > 6){
    byte header = Serial.read(); //read header byte - 80 == P
   
    if(header == 80){
      byte MSB = Serial.read();
      byte LSB = Serial.read();
      byte LSB1 = Serial.read();
      byte MSB1 = Serial.read();
      byte foot = Serial.read();
     
      //make sure it fits the pattern
     
      if(MSB == MSB1 && LSB == LSB1 && header == foot){
        int positionValue = convertBytes(MSB, LSB);
        Serial.print("got a value: ");
       
        Serial.println(positionValue);
      }else{
       Serial.println("that didnt work");
       
       Serial.print("MSB: ");
       Serial.println(MSB);
       
       Serial.print("LSB: ");
       Serial.println(LSB);
       
       Serial.print("LSB1: ");
       Serial.println(LSB1);
       
       Serial.print("MSB1: ");
       Serial.println(MSB1);
       
       Serial.print("foot: ");
       Serial.println(foot);
       
       Serial.println("/////////////////");
      }
     
    }else{
             
       Serial.print("HEADER WAS NOT A P");
             
       Serial.print("header: ");
       Serial.println(header);
       
       Serial.println("/////////////////");
     
    }
   
  }
 
}



int convertBytes(int MSB, int LSB){ 
    //99% sure this is right
    return(MSB << 8) | LSB; //get just the first byte
}

void doMotorThing(int positionValue){
  //do something with the positionValue
 
}
44  Using Arduino / Programming Questions / Re: OneButton library help on: August 31, 2012, 09:28:58 am
Quote
The default values of 600 and 1000 are too long, and too close, in my opinion. I'd use values like 50 and 250, if I was using the library. A 0.05 second hold down time to be recognized as a click and a hold down time of 0.25 seconds to be recognized as a press seem more reasonable to me.

Think about how long you have to hold a key on a keyboard down for it to be recognized. 6/10 of a second is an eternity.

My Thoughts exactly.
Thanks again smiley
45  Using Arduino / Programming Questions / Re: OneButton library help on: August 31, 2012, 07:14:15 am
Thank you very much PaulS !
So actually if in my setup () I'll write something like setClickTicks(400) the click time is 0.4 Seconds?
Pages: 1 2 [3] 4 5 ... 11