Arduino as slave to TX-Controller

Alles rund um TX(T) und RoboPro, mit ft-Hard- und Software
Computing using original ft hard- and software
Forumsregeln
Bitte beachte die Forumsregeln!
Antworten
Klub_Robotik_G-COM
Beiträge: 14
Registriert: 19 Jul 2012, 12:15

Arduino as slave to TX-Controller

Beitrag von Klub_Robotik_G-COM » 25 Jul 2012, 13:12

Hello all,

We are trying to learn how to connect non-FT components; sensors, servos, etc to the TX-Controller, now that the I2C connection has finally arrived.

Our background in electronics is not very good but we know a bit of basic programming from dealing with HTML & PHP.

We have assembled the various pieces so far but would appreciate some guidance in making the correct connections from an Arduino-compatible controller to the TX-C.

Based on Rei Vilo's fantastic website here;
http://reivilofischertechnik.weebly.com ... rface.html
we get that from the TX-C we have this;
Bild

and from the Arduino forum;
http://www.arduino.cc/cgi-bin/yabb2/YaB ... 1208761098
on the slave side, ie. the Arduino; we have this;

Code: Alles auswählen

#include <Wire.h>

void setup()
{
  Wire.begin(2);		    // join i2c bus with address #2
  Wire.onRequest(requestEvent); // register event
  Serial.begin(9600);	     // start serial for output
}

void loop()
{
  delay(100);
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void requestEvent()
{
  static char c = '0';

  Wire.send(c++);
  if (c > 'z')
    c = '0';
}
we have several questions now which would help us to understand how the two come together.

1) on the ROBO Pro side, is "0x14" the address of the Arduino with respect to the TX-C ?

2) in the slave code,
Wire.begin(2); // join i2c bus with address #2
Wire.onRequest(requestEvent); // register event

would the code in "void requestEvent()" be activated by sending/writing "0x02" from ROBO Pro ?

3) can one register more than one 'event', and how would they be called in a switch...case loop ?
would it be something like this ?

Code: Alles auswählen

switch (command) {
  case 0x52: // reset
    mySensor.reset();
    Serial.print("< reset");
    Serial.println();
    break;
  case 0x02: //
    // do something else
    break;
  case 0x03: //
    // do something else again
    break;
}
Thanks in advance for your patience in dealing with very basic questions.

Cheers.
G-COM

Klub_Robotik_G-COM
Beiträge: 14
Registriert: 19 Jul 2012, 12:15

Re: Arduino as slave to TX-Controller

Beitrag von Klub_Robotik_G-COM » 26 Jul 2012, 13:57

thank you very much for your clear reply.

i'm now wondering if it's actually less complicated than i'm making it out to be !

for the case of "RoboPro just to send data to the I2C device";

on the Arduino side, we have to prepare the functions beforehand for each case of byte that will be sent.

would this be how it looks ?

Code: Alles auswählen

#include "Wire.h"

void setup()
{
  // join i2c bus with address #0x14
  Wire.begin(0x14);               
  // register eventS 
  Wire.onReceive(do_servo_1); 
  Wire.onReceive(do_servo_2); 

  //servo assignments
  myservo1.attach(8); // attaches servo on pin 8 to a servo object
  myservo2.attach(9); // attaches servo on pin 9 to a servo object

}


void loop()
{
  command = Wire.read();

  switch (command) {
    case 0x20: // do servo 1
    do_servo_1()
    break;

    case 0x21: // do servo 2
    do_servo_2()
    break;

  }

}


void do_servo_1()
{
	for (pos = 0; pos < 180; pos += 1) 
	  {                                
	    myservo1.write(pos);            
	    delay(15);                     
	  }
	  for (pos = 180; pos>=1; pos-=1) 
	  {                                
	    myservo1.write(pos);          
	    delay(15);                   
	  }
}

void do_servo_2()
{
	for (pos = 0; pos < 180; pos += 1) 
	  {                                
	    myservo2.write(pos);            
	    delay(15);                     
	  }
	  for (pos = 180; pos>=1; pos-=1) 
	  {                                
	    myservo2.write(pos);          
	    delay(15);                   
	  }
}
and then on the ROBO Pro side it's just as simple as one I2C Write element :

a) Address "0x14" and data byte "0x20" - and servo on pin 8 will move.
and
b) Address "0x14" and data byte "0x21" - and servo on pin 9 will move.

have i understood this correctly ?

Klub_Robotik_G-COM
Beiträge: 14
Registriert: 19 Jul 2012, 12:15

Re: Arduino as slave to TX-Controller

Beitrag von Klub_Robotik_G-COM » 27 Jul 2012, 12:20

thanks for the correct syntax.

one question about the (variable?/keyword?) 'howMany', in the above case it would be just '1', right ?

if (for example) it were '2', then the event would be waiting for a second byte to be sent from the TX-C; your informative website has shown us how to do this :)

but, on the Arduino side, how would one separate the first byte (for the switch...case code) and the second byte which would be used for some additional parameter in the function?

Klub_Robotik_G-COM
Beiträge: 14
Registriert: 19 Jul 2012, 12:15

Re: Arduino as slave to TX-Controller

Beitrag von Klub_Robotik_G-COM » 13 Aug 2012, 11:36

Hello all, we're back.

After studying the Arduino forums we have succeeded in making a connection between the TX-C and an Arduino-compatible Spider micro-controller.

With a simple LED code;

Code: Alles auswählen

#include "Wire.h"
int led = 13; //  on-board LED

void setup()
{
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);     

  // join i2c bus with address #0x14
  Wire.begin(0x14);               
  // register event(s)
  Wire.onReceive(ReceiveEvent);     // the Arduino receives data from the TX controller

}

// Loop has nothing to do.
void loop()
{
}

// This is the core function to process the commands and is activated by the Wire.onReceive event. 
void ReceiveEvent(int howMany) {

  switch (Wire.read()) {
    case 0x20: // lamp on
    lamp_on();
    break;

    case 0x21: // lamp off
    lamp_off();
    break;

  }
}

void lamp_on()
{
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
}

void lamp_off()
{
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
}
everything runs ok with the following RPP;
Bild

but when we start using servos, it doesn't execute as expected - could you point us out to where we have made the mistake ?

This is the code on the microcontroller :

Code: Alles auswählen

#include "Wire.h"
#include <Servo.h> 
Servo myservo;  // create servo object to control a servo 

int pos=0;
int val;

void setup()
{
  //servo assignments
  myservo.attach(11); // attaches servo on pin 11 to a servo object
  // initialize the digital pin as an output.
  pinMode(13, OUTPUT);     //  on-board LED


  // join i2c bus with address #0x14
  Wire.begin(0x14);               
  // register event(s)
  Wire.onReceive(ReceiveEvent);     // the Arduino receives data from the TX controller
}

// Loop has nothing to do.
void loop()
{
}

// This is the core function to process the commands and is activated by the Wire.onReceive event. 
void ReceiveEvent(int howMany) {

  switch (Wire.read()) {
    case 0x30: // 
    do_servo_1();
    break;
    
    case 0x31: //
    do_servo_2();
    break;
  }

}

void do_servo_1()
{
  myservo.write(11);                  // sets the servo position
  delay(500);                           // waits for the servo to get there 

  val = 120; 
  myservo.write(val);
  delay(500);       

  val = 90;          
  myservo.write(val);
  delay(500);       

  val = 170;         
  myservo.write(val);
  delay(500);       

// blink for indication
  digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(500);               // wait for half a second
  digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
  delay(500);               // wait for half a second
} 

void do_servo_2()
{
  for (pos = 120; pos < 50; pos -= 1) // goes from 0 degrees to 180 degrees
  {                                 // in steps of 1 degree
    myservo.write(pos);             // tell servo to go to position in variable 'pos'
    delay(15);                      // waits 15ms for the servo to reach the position
  }


// blink for indication
  digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(500);               // wait for half a second
  digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
  delay(500);               // wait for half a second
} 
and this is the RPP that we use :
Bild

Ad2
Beiträge: 306
Registriert: 31 Okt 2010, 22:20

Re: Arduino as slave to TX-Controller

Beitrag von Ad2 » 14 Aug 2012, 11:51

Hi,

I don't have much experience with Arduino but it appears that your event handlers (do_servo) run in interrupt context. Normally interrupt handlers should be as short (in time) as possible because other interrupts are generally blocked. In your case you have delays totalling upto 3 seconds. You haven't said how your program behaves but blocked interrupts could potentially cause the TWI or UART to malfunction. To trigger a complex behaviour like you seem to want, it is better to set a global flag on interrupt and poll that flag in the main loop. Once the loop sees the flag it starts a (ms) timer which value is polled on every pass through the loop and a specific action is taken when it passes through 500, 1000, 1500 etc. At the end of the sequence you clear the flag. With this technique the only busy_wait in your program is the main loop itself and the system only blocks when the total of foreground and background processing exceeds the CPU capacity.

Ad

Klub_Robotik_G-COM
Beiträge: 14
Registriert: 19 Jul 2012, 12:15

Re: Arduino as slave to TX-Controller

Beitrag von Klub_Robotik_G-COM » 15 Aug 2012, 11:09

Hello Ad,

Thank you for your reply but we didn't understand too much as our experience is even less!

Our aim is to connect the TX-Controller to a servo microcontroller to handle more than 4 servo motors. (In our case, we are using a Spider (Arduino-compatible) Servo microcontroller.)

We then pre-load the Spider with several "subprograms" to run the servos based on a simple command (I2C Write) from the TX-Controller.

Based on the information given above on connecting a TX-C via I2C bus, we use the ReceiveEvent subroutine and loop() has nothing to do, and for the LED switch program, this works okay.

However, when we try this similar approach with servos, it doesn't work.

The "5 sec delay" was an addition to the program when we thought the microcontroller wasn't being given enough time to complete it's task by the TX-C. (It was initially a closed loop exactly like the program for the LED switch.)

What you explained does make sense, the "complex behaviour" and "long delay" and we figure that loop() now should be used but are unsure how this would look.

Could you clarify in broad code structure what, "it is better to set a global flag on interrupt and poll that flag in the main loop." - would look like ?

Klub_Robotik_G-COM
Beiträge: 14
Registriert: 19 Jul 2012, 12:15

Re: Arduino as slave to TX-Controller

Beitrag von Klub_Robotik_G-COM » 23 Aug 2012, 12:03

Hello Rei Vilo,

have you been able to look at the problem ?

regarding Ad2's comment;
"it is better to set a global flag on interrupt and poll that flag in the main loop."
that would mean triggering the ReceiveEvent (based on a flag) in the loop(), which is not possible, is it ?

Ad2
Beiträge: 306
Registriert: 31 Okt 2010, 22:20

Re: Arduino as slave to TX-Controller

Beitrag von Ad2 » 23 Aug 2012, 14:39

Sorry I forgot...

maybe something like this:

Code: Alles auswählen

int cmd_1_received; //your global flag
int timer_1; //this variable increments each ms

void cmd_received() //your event handler
{ if (command == command_1)
  { cmd_1_received = 1;
    timer_1 = 0;
  }
} 

void loop()
{
  if (cmd_1_received)
  { if (timer_1 > 5000)
    { ...
      cmd_1_received = 0;
    }
    else if (timer_1 > 4000)
      ...
    else if (timer_1 > 3000)
      ...
    else if (timer_1 > 2000)
      ...
    else
      ...
  }
}

Klub_Robotik_G-COM
Beiträge: 14
Registriert: 19 Jul 2012, 12:15

Re: Arduino as slave to TX-Controller

Beitrag von Klub_Robotik_G-COM » 29 Aug 2012, 08:10

Ad2 hat geschrieben:Sorry I forgot...

maybe something like this:

Code: Alles auswählen

int cmd_1_received; //your global flag
int timer_1; //this variable increments each ms

void cmd_received() //your event handler
{ if (command == command_1)
  { cmd_1_received = 1;
    timer_1 = 0;
  }
} 

void loop()
{
  if (cmd_1_received)
  { if (timer_1 > 5000)
    { ...
      cmd_1_received = 0;
    }
    else if (timer_1 > 4000)
      ...
    else if (timer_1 > 3000)
      ...
    else if (timer_1 > 2000)
      ...
    else
      ...
  }
}
thanks for the reply, that means the ReceiveEvent is triggered in the loop(), which i'm not sure is possible ??

meanwhile, have read this on another thread;
Re: I²C für Einsteiger...
http://forum.ftcommunity.de/viewtopic.p ... uino#p8499
vleeuwen hat geschrieben: ...

The TX-C has nota preprosesor. So all processing of the raw data need to be done at RoboPro level.
This makes it rather slow.
For example the RoboPro I2C lib for the stepper controller shows that this is possible but complex.
And this lib is only offering the basic read and write operations for that stepper device and not how to make use of all the functionality this device is offering.

So how it works it not the problem, there is no need for a new description.
The main problem is the development of functional sensors and actuators electronic and software drivers.
In a way that these hardware will be accessable for the normal FT end users.
And this is a lot more than buying an I2C sensor kit from Conrad, Microchip of others.
could this be a reason why the servo subprogram above doesn't work ?
when we 'poke' the address and send the data for the Switch...case loop, the servo does move a bit, in the correct direction, but not to the endpoint as determined by the subprogram on the slave microcontroller.

is this a limitation of the TX-C ?

Ad2
Beiträge: 306
Registriert: 31 Okt 2010, 22:20

Re: Arduino as slave to TX-Controller

Beitrag von Ad2 » 29 Aug 2012, 16:19

that means the ReceiveEvent is triggered in the loop()
That is for sure not my intention! The ReceiveEvent sets the flag (cmd_received is the ReceiveEvent event handler). The loop() continuously polls this flag, performs some activity while it is set, and clears it once everything is done. The activity itself is typically controlled by a state machine. In this case timer_1 is the state variable which is increased every millisecond and reset on each received command.

Antworten