Go Down

Topic: lego ir 4channel transmiter with mixer  (Read 324 times) previous topic - next topic

salvo200380

May 03, 2015, 06:56 pm Last Edit: May 03, 2015, 06:58 pm by salvo200380
hello guy's
just finish to test my diy controller for lego power functions
it has 4channels reversable and 2 mixer. it's an rc style radio transmitter

there are many library which do the dirty job to translate some software line into a real comunication with the receiver, but i decided to work it out all in a sketch

i'm not a very skilled programmer so maybe you'll find some newbie errors but any way it work very well!!

here is the code i want to share

Enjoy
Salvo

Code: [Select]

/*
  lego ir speed remote control arduino

 futures:
 4 tx channel (a, b, c, d)

 reverse a,b,c,d
 mixer   a+b  c+d


 The circuit:
 * channel A to analog input 0
 * channel B to analog input 1
 * channel c to analog input 2
 * channel d to analog input 3
 * pin 4 mixer a
 * pin 5 mixer b
 * pin 6 ir transistor input (can't supply the ir diode directly from arduino!!!)
 * pin 7 a reverse
 * pin 8 b reverse
 * pin 9 c reverse
 * pin 10 d reverse



 */


const int mixa = 4;
const int mixb = 5;
const int ir = 6;
const int reva = 7;
const int revb = 8;
const int revc = 9;
const int revd = 10;



int nibble1;
int nibble2;
int nibble3;
int nibble4;
int nibble5;
int nibble6;
int nibble7;
int nibble8;
int nibble;
int pota ;
int potb ;
int potc ;
int potd ;
int ch1;
int ch2;
int ch3;
int ch4;



void setup()
{
  Serial.begin(9600);
  pinMode(ir, OUTPUT);
  pinMode (reva, INPUT_PULLUP);
  pinMode (revb, INPUT_PULLUP);
  pinMode (revc, INPUT_PULLUP);
  pinMode (revd, INPUT_PULLUP);
  pinMode (mixa, INPUT_PULLUP);
  pinMode (mixb, INPUT_PULLUP);

}

void loop()
{
  get_a();
  get_b();
  
  if (digitalRead(mixa) == LOW) {
    mixer_a();
  }
  
   if (digitalRead(mixb) == LOW) {
    mixer_b();
  }

  if (digitalRead (reva) == HIGH)
  {
    reverse_a();

  }

  if (digitalRead (revb) == HIGH)
  {
    reverse_b();
  }

  if (digitalRead (revc) == HIGH)
  {
    reverse_c();
  }

  if (digitalRead (revd) == HIGH)
  {
    reverse_d();

  }

  

  
  mapping_a();
  mapping_b ();
  nibble1 = 4 |1 ;
  nibble2 = pota;
  nibble3 = potb;
  nibble4 = (15 ^ nibble1 ^ nibble2 ^ nibble3);
  nibble5 = 4 | 0;
  nibble6 = potc;
  nibble7 = potd;
  nibble8 = (15 ^ nibble5 ^ nibble6 ^ nibble7);
  send_message();


}

void get_a()
{
  pota = analogRead(A0) / 58;
  potb = analogRead(A1) / 58;

  if (pota < 1) {
    pota = 1;
  }

  if (pota > 15) {
    pota = 15;
  }
  if (potb < 1) {
    potb = 1;
  }
  if (potb > 15) {
    potb = 15;
  }
}

void get_b() {
  potc = analogRead(A2) / 58;
  potd = analogRead(A3) / 58;

  if (potc < 1) {
    potc = 1;
  }

  if (potc > 15) {
    potc = 15;
  }
  if (potd < 1) {
    potd = 1;
  }
  if (potd > 15) {
    potd = 15;
  }
}

void reverse_a ()
{
  if (pota < 8) {
    pota = 8 + (8 - pota);
  }
  else
  {
    if (pota > 8)
    {
      pota = 8 - (pota - 8);
    }
  }

}


void reverse_b ()
{
  if (potb < 8)
  {
    potb = 8 + (8 - potb);
  }
  else
  {
    if (potb > 8)
    {
      potb = 8 - (potb - 8);
    }
  }
}
void reverse_c ()
{
  if (potc < 8) {
    potc = 8 + (8 - potc);
  }
  else
  {
    if (potc > 8)
    {
      potc = 8 - (potc - 8);
    }
  }

}

void reverse_d ()
{
  if (potd < 8) {
    potd = 8 + (8 - potd);
  }
  else
  {
    if (potd > 8)
    {
      potd = 8 - (potd - 8);
    }
  }

}
void mixer_a ()
{
 
     int delta_b;
    
     delta_b = potb  - 8;
    
    
  ch1 = pota + delta_b;
  ch2 = pota - delta_b;
  
  if (ch1 < 1)
  {ch1 = 1;}
  if(ch2 < 1)
  {ch2 = 1;}
  if (ch1 > 15)
  {ch1 = 15;}
 if (ch2 > 15)
  {ch2 = 15;}
  
pota= ch1;
potb= ch2;
  
}

void mixer_b ()
{
 
     int delta_d;
    
     delta_d = potd  - 8;
    
    
  ch3 = potc + delta_d;
  ch4 = potc - delta_d;
  
  if (ch3 < 1)
  {ch3 = 1;}
  if(ch4 < 1)
  {ch4 = 1;}
  if (ch3 > 15)
  {ch3 = 15;}
 if (ch4 > 15)
  {ch4 = 15;}
  
potc= ch3;
potd= ch4;
  
}

void mapping_a ()
{

  //pot max = 993, pot min = 125


  if (pota < 8) {
    pota = 8 - pota;
  }
  if (pota > 8) {
    pota = (8 - (pota - 8)) + 8;
  }

  //pot max = 993, pot min = 125

  if (potb < 8) {
    potb = 8 - potb;
  }
  if (potb > 8) {
    potb = (8 - (potb - 8)) + 8;
  }
}


void mapping_b ()
{

  //pot max = 993, pot min = 125


  if (potc < 8) {
    potc = 8 - potc;
  }
  if (potc > 8) {
    potc = (8 - (potc - 8)) + 8;
  }

  //pot max = 993, pot min = 125

  if (potd < 8) {
    potd = 8 - potd;
  }
  if (potd > 8) {
    potd = (8 - (potd - 8)) + 8;
  }
}


void ir_mark()
{
  digitalWrite (ir, HIGH);
  delayMicroseconds (10);
  digitalWrite (ir, LOW);
  delayMicroseconds (10);
  digitalWrite (ir, HIGH);
  delayMicroseconds (10);
  digitalWrite (ir, LOW);
  delayMicroseconds (10);
  digitalWrite (ir, HIGH);
  delayMicroseconds (10);
  digitalWrite (ir, LOW);
  delayMicroseconds (10);
  digitalWrite (ir, HIGH);
  delayMicroseconds (10);
  digitalWrite (ir, LOW);
  delayMicroseconds (10);
  digitalWrite (ir, HIGH);
  delayMicroseconds (10);
  digitalWrite (ir, LOW);
  delayMicroseconds (10);
  digitalWrite (ir, HIGH);
  delayMicroseconds (10);
  digitalWrite (ir, LOW);
  delayMicroseconds (10);
}

void nibble_send ()
{
  if (bitRead (nibble, 3) == 0) {
    zero();
  }
  else
  {
    uno();
  }

  if (bitRead (nibble, 2) == 0) {
    zero();
  }
  else
  {
    uno();
  }

  if (bitRead (nibble, 1) == 0) {
    zero();
  }
  else
  {
    uno();
  }

  if (bitRead (nibble, 0) == 0) {
    zero();
  }
  else
  {
    uno();
  }

}

void uno ()
{
  ir_mark();
  delayMicroseconds (555);
}

void zero ()
{
  ir_mark();
  delayMicroseconds (265);
}

void  start_stop () {
  ir_mark();
  delayMicroseconds (1028);

}


void message_a ()
{
  start_stop();
  nibble = nibble1;
  nibble_send();
  nibble = nibble2;
  nibble_send();
  nibble = nibble3;
  nibble_send();
  nibble = nibble4;
  nibble_send();
  start_stop();
}

void message_b ()
{
  start_stop();
  nibble = nibble5;
  nibble_send();
  nibble = nibble6;
  nibble_send();
  nibble = nibble7;
  nibble_send();
  nibble = nibble8;
  nibble_send();
  start_stop();
}

void send_message ()
{
  message_a();
  delay (16);
  message_b();
  delay (16);
  message_a();
  delay (16);
  message_b();
  delay (16);
  message_a();
  delay (16);
  message_b();
  delay (16);
  message_a();
  delay (16);
  message_b();
  delay (16);
  message_a();
  delay (16);
  message_b();


}








RXvol

Hello all,

The starter of this thread pushed me to process with LEGO Powerfunctions on Trains + the older LEGO RC Trains IR protocol with NO explaination on the internet.
With some tools reverse engineering the bitstreams results in this:

Start = Stop   is bitstream 36kHz with 10 bits en pause 1930 mu s
Uno is bitstream 36kHz with 10 bits and pause 280 mu s
Zero is bitstream 36kHz with 10 bits en pause 844 mu s
1 bit has a duty-cycle 16 mu s high and 11,5 mu s low

pauze (common factor 18 ms, dus verhoudingen
Channel actie bitstreams blok-pauze-blok-pauze-blok-pauze-blok)
1 up Start 1111 1111 1110 0001 Stop 3+2+2
     1000 0111 1111 1110 1001 1000 4+5+3
1 down Start 1111 1111 1101 0010 Stop 2+2+3  
       Start 0111 1111 1101 1010 Stop 3+2+3
1 stop Start 0111 1111 1111 1000 Stop       3+2+2
        Start 1111 1111 1111 0000 Stop --------
1 horn Start 1111 1111 1100 0011 Stop --------
       Start 0111 1111 1100 1011 Stop --------
2 up   Start 1110 1111 1110 0010 Stop 2+3+5
        Start 0110 1111 1110 1010 Stop --------
2 down Start 1110 1111 1101 0011 Stop 5+3+3
        Start 0110 1111 1101 1011 Stop --------
2 stop Start 1110 1111 1111 0001 Stop 5+4+4
       Start 0110 1111 1111 1001 Stop --------
2 horn Start 1110 1111 1100 0100 Stop --------
       Start 0110 1111 1100 1100 Stop --------
3 up Start 1101 1111 1110 0011 Stop 5+4+2
       Start 0101 1111 1110 1011 Stop --------
3 down Start 1101 1111 1101 0100 Stop 3+2+2
       Start 0101 1111 1101 1100 Stop --------
3 stop Start 1101 1111 1111 0010 Stop 5+4+5
       Start 0101 1111 1111 1010 Stop --------
3 horn Start 1101 1111 1100 0101 Stop --------
        Start 0101 1111 1100 1101 Stop --------
4 up Start 1100 1111 1110 0100 Stop 2+3+5
       Start 0100 1111 1110 1100 Stop --------
4 down Start 1100 1111 1110 0101 Stop 3+2+3
      Start 0100 1111 1110 1101 Stop --------
4 stop Start 0100 1111 1111 1011 Stop 3+2+3
       Start 1100 1111 1111 0011 Stop 2+3+3
4 horn Start 1100 1111 1100 0110 Stop --------
         Start 0100 1111 1100 1110 Stop --------


(STOP- button keeps repeating when hold, all others (UP, DOWN, HORN) send only once a message

1e nibble: bit1 bit2 bit3 bit4
Kanaal 1 toggle   1    1    1
Kanaal 2 toggle   1    1    0
Kanaal 3 toggle   1    0    1
Kanaal 4 toggle   1    0    0

2e nibble            1   1    1     1

3e nibble            1   1  
Up    1      0
Down    0      1
Stop    1      1
Horn    1      0

4e nibble toggle   ?    ?      ?    (checksum ???)
                               Togglebit reverse from 1st nibble bit1

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy