Servo control

//-------------------ARDUINO CODE----------------------//
//Arduino 1 code:

void setup()
{
  Serial.begin(9600);
}


void loop()
{
  while(Serial.available() == 0);
  {
    int pos = Serial.read() - '0';
    analogWrite(A0, pos);
    Serial.flush();
  }
}
//Arduino 2 code:

#include <Servo.h>

Servo myservo;

void setup()
{
  myservo.attach(9);
  Serial.begin(9600);
}


void loop()
{
  int data = analogRead(A0);
  Serial.println(data);
  myservo.write(data);
  //Servo.flush();
}
//------------------------PROCESSING APPLET-------------------//

//code:

import processing.serial.*;
import controlP5.*;

Serial port;
ControlP5 cp5;

int tilt = 0;

void setup()
{
size(200, 200);

port = new Serial(this, "COM14", 9600);
//port.bufferUntil('\n');

cp5 = new ControlP5(this);

cp5.addSlider("tilt")
     .setPosition(88,7)
     .setSize(20,180)
     .setRange(0,180)
     .setValue(90)
     ;
}

void draw()
  {
    background(0);
    println(tilt);
    port.write(tilt);
  }

Searching for a while, i found these

where a similar problem was raised & a person suggested something like I thought with analog read & write ()s .

And out of all the methods discussed on that thread, you decided to go with the one that required hardware you don't have?

Well I tried with both the low pass filter way & the i2c way. low pass filter had some glitches. Sometimes it worked just fine. The system is not dependable for crucious moments. moving on to I2C.

The code for the arduino which will receive serail data from the Processing app is :

#include <Wire.h>

int data = 0;

void setup()
{
  Serial.begin(9600);
  Wire.begin();
}

void loop()
{
  while(Serial.available() == 0)
  {
    int data = Serial.read() - '0';
    Wire.beginTransmission(4);
    Wire.write(data);
    Wire.endTransmission();
    Serial.flush();
  }
  delay(50);
}

& the code for the arduino that is connected to the previous arduino with I2C & a servo is

#include <Wire.h>
#include <Servo.h>

Servo myservo;
int x = 0;

void setup()
{
  Wire.begin(4);                // join i2c bus with address #4
  Wire.onReceive(receiveEvent); // register event
  //Serial.begin(9600);
  myservo.attach(9);
}

void loop()
{
  //delay(100);
  myservo.write(x);
  //Servoflush();
}

void receiveEvent(int howMany)
{
  while( Wire.available() == 0) // loop through all but the last
  {
      x = Wire.read();    // receive byte as an intege
  }
}

The problem is the servo keeps on moving . Never stops & is not affected by the serial data coming over the first arduino.
I guess there is some random data like the -49 for the subtraction (- '0') that we are employing in the first arduino program is causing the problem. My best guess. Any more problems sorted out & fixable is needed. help again. :frowning:

130212-235520.jpg

What does this code do?

while(Wire.available() == 0)
{
  x = Wire.read();    // receive byte as an intege
}

\until & unless the data over I2C is 0, it'll keep on reading & set that value to a variable x. This variable is then used to define the position of a servo

dattasaurabh82:
\until & unless the data over I2C is 0, it'll keep on reading & set that value to a variable x. This variable is then used to define the position of a servo

Look again.

I've modified the reciever arduino code a little. But not working still. Is it because there is something missing in the code or since I've not used Pull ups in tn the I2C bus? The servo keeps on rotating.

#include <Wire.h>
#include <Servo.h>

Servo myservo;
int pos = 0;

void setup()
{
  Wire.begin(4);                
  Wire.onReceive(receiveEvent); 
  myservo.attach(9);
}

void loop()
{
  delay(100);
}

void receiveEvent(int howMany)
{
  pos = Wire.read();    
  myservo.write(pos);
}

Does your servo work correctly if you just call servo.write() with a sequence of values to move it through a sequence of positions? You need to prove it's working correctly before you try to control it remotely.

Is your interrupt actually being called and receiving the value that was sent? Rather than write it directly to the servo, I suggest you write it to a volatile variable and then in loop read that and call servo.write to move the servo to that position - then you can use Serial.print statements to show what movements were received.

My servo's working fine(ran the "sweep" example with success). Also I tried to read the data coming to the 2nd arduino in the serial monitor (for my case COM-4) as I applied on the slider in applet running by processing, sending serial data to the first arduino(COM-14). I was communicating successfully.
Here are the codes :
------------Processing applet code--------------

import processing.serial.*;
import controlP5.*;

Serial port;
ControlP5 cp5;

int tilt = 0;

void setup() 
{
size(200, 200);

port = new Serial(this, "COM4", 9600);
//port.bufferUntil('\n');

cp5 = new ControlP5(this);

cp5.addSlider("tilt")
     .setPosition(88,7)
     .setSize(20,180)
     .setRange(0,180)
     .setValue(90)
     ;
}

void draw() 
  {
    background(0);
    println(tilt);
    port.write(tilt);
  }

Arduino code which will receive serial data from the Processing & communicate with other arduino through I2C.

------------Arduino One Code-------------------

#include <Wire.h>

void setup()
{
  Wire.begin();
  Serial.begin(9600);
}

int x = 0;

void loop()
{
  while(Serial.available())
  {
    x = Serial.read();
    
    Wire.beginTransmission(4);
    Wire.write(x);
    Wire.endTransmission();
    
    Serial.flush();
    
    delay(20);
  }
}

the code for Arduino which will receive data fro the 1st arduino & print the results in the serial monitor.

----------------Arduino Two Code--------------------

#include <Wire.h>
#include <Servo.h>

Servo myservo;

void setup()
{
  Serial.begin(9600);
  myservo.attach(9);
  Wire.begin(4);                
  Wire.onReceive(receiveEvent); 
}

void loop()
{ 
   delay(5);
}

void receiveEvent(int howMany)
{
   int x = Wire.read();
   myservo.write(x);
   Serial.println(x);
   Serial.flush();  
  }

I guess the servo is getting same value multiple times & thus is freaking out(As it is coming serially all the time). I need to use something that will let the servo pick up a changed values once (as they change) only to make it move & not the same value continuously coming over serially to first arduino & to it through I2C finaly.
Something to flush the excess data.

Can any body test anything on this & help with a modified code please?

Isn't the Wire event handler called from an interrupt? If so you want to avoid doing Serial I/O in that - I suggest using a volatile variable to store the received value and put code in loop() to pass it on to the servo, and print the value out from there. Is Arduino 2 receiving the correct values?

Yes; Arduino 2 is receiving the correct values. Can you please state how to do that. I'm new new to this.
Do you mean something like this:

#include <Wire.h>
#include <Servo.h>

Servo myservo;
volatile int x = 0;

void setup()
{
  Serial.begin(9600);
  myservo.attach(9);
  Wire.begin(4);                
  Wire.onReceive(receiveEvent); 
}

void loop()
{ 
   myservo.write(x);
   Serial.println(x);
   Serial.flush();  
   delay(5);
}

void receiveEvent(int howMany)
{
   x = Wire.read();
   
  }

Change the int to a byte, but otherwise yes:

volatile byte x = 0;

Does it print the correct values? Does the servo correctly move to the corresponding positions?

Thanks PETER for your constant support. Power cut is going on here. Also tired of all the discussions through-out the day. will let you know tomorrow.
Should I also keep the out-put value from the arduino-one as "byte" or "int"? And the servo.Write() & serial.Println() should be in void loop() or event-handler loop?

It works. But the response is pretty slow unlike the serial communication. :~

What do you mean by "pretty slow"?

It felt like the buffer was not completely cleared & the motor was turning against it's will . Some times it tries to rotate completely, but couldn't & the slow response is due to the delay's I used on both the boards.

Also can I communicate between ATtiny85/45 & Arduino UNo using I2C. Separate I2C lines are not present in ATtinys. So we might need an USI-I2C converter sort of thing .
I'm asking this because I want to replace my Arduino-2 with n ATtiny. Is that possible?

dattasaurabh82:
It felt like the buffer was not completely cleared & the motor was turning against it's will . Some times it tries to rotate completely, but couldn't & the slow response is due to the delay's I used on both the boards.

I'm staring blankly at that and trying to figure out what on Earth it means. I can only guess there's some lag between your user interface input and the physical servo movement, which was already implied by your previous post, and I was hoping you'd say how much lag there was.

Do you know how fast that Processing code is sending positions to Arduino1? It's probably trying to send them a lot faster than your serial stream can deliver them, which means you'll have a backlog in the output stream which will delay any changes. You really need to limit the rate at which your processing code sends the position updates, to keep that well below the rate that the serial port can deliver them. One way to do that is to enforce a minimum interval between updates. Another way is to only send the new value if it differs from the previous value. Also take out all the delay() calls from your Arduino code. It might reduce the amount of data being passed to Arduino2 if you completely drain the incoming serial stream at Arduino1 and only send the final position over the wire to Arduino2.

Though the delay's not much, it is noticeable. Sorry if I was not able to convey the msg very clearly before . I tried, before you replied, with deleting all the delays in the Arduino code & that creates trouble definitely. So after 3 experimentation, I fixed the above given delays. Also I sorted out the sending of serial data to the com port from the applet by the your concept of - "Sending only the new values at some small 20ms delays", kind of solved the problem.