Problem to remote 2 train with Lego Power Function.

I am trying to remote 2 lego trains with arduino mega 2560 and lego power function.

The problem is that when the first train stop, it should not move when second train start moving after some delay.

Here is the code

  if (detected == LOW){
    Serial.print("Sensor 1");    
     delay(7000);
      lego.SingleOutput(0,PWM_FLT,RED,CH1); // [b]first train[/b]
      delay(2000);
       lego.SingleOutput(0,PWM_REV5,BLUE,CH1); // [b]second train
[/b]
   }

Is possible to remote properly two train with the same ir led or should I have different ir led for each train?

The problem is that when the first train stop, it should not move when second train start moving after some delay.

what does that mean? if it should not move then just don't tell the train to move...

You need to post a link to the documentation for the Lego library you are using.

...R

I use this lego power function library that can be found at this post http://forum.arduino.cc/index.php?topic=89310.0. Or it there an newer version of lego power function library that I should use?

Ken76:
I use this lego power function library that can be found at this post

Is there no online documentation so that I don't have to download stuff to my PC?

...R

Here are two links about some info about Lego Power Function. I couldn’t find more info.

Use different channels

I didn't help to change channel. I also tried to set RED and BLUE for both trains, but that didn't either help. Is there something else to try?

Does it work independently when you use the lego transmitter?

vinceherman:
Does it work independently when you use the lego transmitter?

Then it works fine with two trains using the lego transmitter.

Ken76:
Here are two links about some info about Lego Power Function. I couldn’t find more info.

I had hoped that others had come along who know more about this than my near-zero knowledge.

From Github this is the .h file

/*
LEGO Power Functions protocol for the arduino.
20-04-2009
Version 1.1 

Changelist:
 - Changed the timing in oscillationWrite from 13us to 9us.
 - Forgot to set the ir-pin to OUTPUT
 - added support for SingleOutput the "Clear - Set - Toggle"

This code is based on the code of Bob Kojima 01-19-2008

I have modified it to work on the Arduino.

Roland Wiersma
*/

#ifndef legopowerfunctions_h
#define legopowerfunctions_h

#include <Arduino.h>

//SinglePin & SingleOutput modes
#define CONTINUOUS 0x2
#define TIMEOUT 0x3
#define PWM 0x0
#define CST 0x2 //Clear - Set - Toggle

//ComboPWM & SingleOutput pwm steps
#define PWM_FLT 0x0
#define PWM_FWD1 0x1
#define PWM_FWD2 0x2
#define PWM_FWD3 0x3
#define PWM_FWD4 0x4
#define PWM_FWD5 0x5
#define PWM_FWD6 0x6
#define PWM_FWD7 0x7
#define PWM_BRK 0x8
#define PWM_REV7 0x9
#define PWM_REV6 0xA
#define PWM_REV5 0xB
#define PWM_REV4 0xC
#define PWM_REV3 0xD
#define PWM_REV2 0xE
#define PWM_REV1 0xf

//SingleOutput Clear - Set - Toggle steps
#define CL_C1_CL_C2 0x0
#define ST_C1_CL_C2 0x1
#define CL_C1_ST_C2 0x2
#define ST_C1_ST_C2 0x3
#define INC_PWM 0x4
#define DEC_PWM 0x5
#define FULL_FWD 0x6
#define FULL_REV 0x7
#define TOG_FWD_REV 0x8

//ComboMode steps
#define RED_FLT 0x0
#define RED_FWD 0x1
#define RED_REV 0x2
#define RED_BRK 0x3
#define BLUE_FLT 0x0
#define BLUE_FWD 0x4
#define BLUE_REV 0x8
#define BLUE_BRK 0xC

//channels
#define CH1 0x0
#define CH2 0x1
#define CH3 0x2
#define CH4 0x3

//SinglePin & SingleOutput output
#define RED 0x0
#define BLUE 0x1

//SinglePin functions
#define NO_CHANGE 0x0
#define CLEAR 0x1
#define SET 0x2
#define TOGGLE 0x3

//SinglePin pin
#define PIN_C1 0x0
#define PIN_C2 0x1

class LEGOPowerFunctions
{
  private:
    void pf_send(int code1, int code2);
    void oscillationWrite(int pin, int time);
    void start_stop_bit();
    void message_pause(int channel, int count);

  public:
    LEGOPowerFunctions(int IR_Pin);
    void SingleOutput(int mode, int step, int output, int channel);
    void SinglePin(int mode, int function, int pin, int output, int channel);
    void ComboMode(int blue_speed, int red_speed, int channel);
    void ComboPWM(int blue_pwm, int red_pwm, int channel);
};

#endif

and this is the .cpp file

/*
LEGO Power Functions protocol for the arduino.
20-04-2009
Version 1.1 

Changelist:
 - Changed the timing in oscillationWrite from 13us to 9us.
 - Forgot to set the ir-pin to OUTPUT
 - added support for SingleOutput the "Clear - Set - Toggle"

This code is based on the code of Bob Kojima 01-19-2008

I have modified it to work on the Arduino.

Roland Wiersma
*/

#include "legopowerfunctions.h"

int _IR_Pin;
int toggle[4] = {0, 0, 0, 0};
int delay_code1, delay_code2, messagecount = 0;

LEGOPowerFunctions::LEGOPowerFunctions(int IR_Pin) {
    _IR_Pin = IR_Pin;
    pinMode(IR_Pin, OUTPUT);
}

void LEGOPowerFunctions::SingleOutput(int mode, int step, int output, int channel) {
    int nib1, nib2, nib3, nib4;

    //set nibs
    nib1 = toggle[channel] | channel;
    nib2 = 0x4 | mode | output;
    nib3 = step;
    nib4 = 0xf ^ nib1 ^ nib2 ^ nib3;

    message_pause(channel, messagecount);
    pf_send(nib1 << 4 | nib2, nib3 << 4 | nib4);

    if (toggle[channel] == 0)
        toggle[channel] = 8;
    else
        toggle[channel] = 0;
}

void LEGOPowerFunctions::SinglePin(int mode, int function, int pin, int output, int channel) {
    int nib1, nib2, nib3, nib4;

    //set nibs
    nib1 = toggle[channel] | channel;
    nib2 = 0x00 | mode;
    nib3 = output << 4 | pin << 3 | function;
    nib4 = 0xf ^ nib1 ^ nib2 ^ nib3;

    message_pause(channel, messagecount);
    pf_send(nib1 << 4 | nib2, nib3 << 4 | nib4);

    if (toggle[channel] == 0)
        toggle[channel] = 8;
    else
        toggle[channel] = 0;
}

void LEGOPowerFunctions::ComboMode(int blue_speed, int red_speed, int channel) {
    int nib1, nib2, nib3, nib4;

    //set nibs
    nib1 = channel;
    nib2 = 0x01;
    nib3 = blue_speed | red_speed;
    nib4 = 0xf ^ nib1 ^ nib2 ^ nib3;

    message_pause(channel, messagecount);
    pf_send(nib1 << 4 | nib2, nib3 << 4 | nib4);
}

void LEGOPowerFunctions::ComboPWM(int blue_pwm, int red_pwm, int channel) {
    int nib1, nib2, nib3, nib4;

    //set nibs
    nib1 = 0x4 | channel;
    nib2 = blue_pwm;
    nib3 = red_pwm;
    nib4 = 0xf ^ nib1 ^ nib2 ^ nib3;

    message_pause(channel, messagecount);
    pf_send(nib1 << 4 | nib2, nib3 << 4 | nib4);
}

void LEGOPowerFunctions::pf_send(int code1, int code2) {

    if (code1 == delay_code1 && code2 == delay_code2) 
    {
        if (messagecount < 4)
            messagecount++;
    } else 
    {
        delay_code1 = code1;
        delay_code2 = code2;
        messagecount = 0;
    }
	
    cli(); // make it uninterruptable
    start_stop_bit();

    int x = 128;
    while (x) {
        oscillationWrite(_IR_Pin, 156);

        if (code1 & x) //high bit
            delayMicroseconds(546);
        else //low bit
            delayMicroseconds(260);

        x >>= 1; //next bit
    }

    x = 128;
    while (x) {
        oscillationWrite(_IR_Pin, 156);

        if (code2 & x) // high bit
            delayMicroseconds(546);
        else //low bit
            delayMicroseconds(260);

        x >>= 1; //next bit
    }
    start_stop_bit();
    sei();

}

void LEGOPowerFunctions::start_stop_bit() {
    oscillationWrite(_IR_Pin, 156);
    delayMicroseconds(1014);
}

/*
The IR signal is 38Khz
1 pulse is 26 microseconds (1/1.000.000)
So the delay should be 13us, but because of internal delay 9us is more close.
I have timed it with a scope. 13us delay equals about 28khz.
10us is about 35khz. I have not timed 9us but i think its close.
*/
void LEGOPowerFunctions::oscillationWrite(int pin, int time) {
    for (int i = 0; i <= time / 26; i++) {
        digitalWrite(pin, HIGH);
        delayMicroseconds(9);
        digitalWrite(pin, LOW);
        delayMicroseconds(9);
    }
}

void LEGOPowerFunctions::message_pause(int channel, int count) {
    unsigned char a = 0;

    if (count == 0)
        a = 4 - channel;
    else if (count == 1 || count == 2)
        a = 5;
    else if (count == 3 || count == 4)
        a = (6 + 2 * channel);

    delay(a * 16);
}

…R

And my brief reading of the .cpp file leads me to conclude that it is cr*p. For example the 38kHz IR carrier is produced using delayMicroseconds(). And there are other delay()s all over the place. I cannot see how that could be used to control two different things at the same time.

This Thread about IR comms may be of interest if you want to write your own equivalent of the library.

But you really need to find a document that provides the specifications against which a program should be written.

...R

I did try with two ir leds at the same time, but the results were the same. Unfortunately I didn't find any more documents. But thanks Robin2 for trying to help me.