Jump to content
THIS IS THE TEST SITE OF EUROBRICKS! ×
THIS IS THE TEST SITE OF EUROBRICKS!

Recommended Posts

Posted (edited)

LEGO Technic 8081 B Model with a Servo, M model, IR receiver and battery box, together with a custom Arduino controller.

OzShan's post about Power Functions got my wheels turning so I stopped by RadioShack and picked up an Arduio Explora and an IR LED and built this:

14433019812_9f6eacb654_c.jpg

Here is the code:

/*
Simple Lego Remote
Description:
Arudio Esplora code to send LEGO Power Functions
IR signals based on the joystick input.

Lego Power Functions Details:
 Mode: Combo PWM Mode
 Channel: CH1
 Center Position: Float

Contributors:
 LEGO PF IR commands: SuperCow - [url="http://forum.arduino.cc/index.php?topic=38142.0"]http://forum.arduino...p?topic=38142.0[/url]
 IR Pulse timing: David Cuartielles
 Combo PWM Mode and Esplora mapping: Bzroom - Kincaid05@gmail.com
*/

#include <Esplora.h>

// LEGO Power Functions constants
// modes
#define COMBO_PWM_MODE 0x4

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

// PWM speed 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

// PWM Speed steps in a logic order from full reverse to full forward.
// There are two zeros to increase the dead zone. They can be brake or float.
byte PWN_ORDERED[16] = {PWM_REV7, PWM_REV6, PWM_REV5, PWM_REV4, PWM_REV3, PWM_REV2, PWM_REV1, PWM_FLT, PWM_FLT, PWM_FWD1, PWM_FWD2, PWM_FWD3, PWM_FWD4, PWM_FWD5, PWM_FWD6, PWM_FWD7 };
byte PWM_ORDERED_COUNT_MINUS_ONE = 15;

// Experiment Settings
int IRPin = 1;
int LEGOChannel = CH1;

// Called by platform. Configure the hardware and sub systems.
void setup()
{
pinMode(IRPin, OUTPUT);
digitalWrite(IRPin, LOW);
}

// Called by platform repeatedly. Execute logic here.
void loop()
{
readJoystickAndSendMessage();
}

// Read the explora joy stick. Map joystick values to LEGO Power Functions IR red and
// blue channels. Provides channel reversal.
void readJoystickAndSendMessage()
{
int xAxis = Esplora.readJoystickX();
int yAxis = Esplora.readJoystickY();

int redReverse = -1;
int blueReverse = -1;
byte red = map(yAxis * redReverse, -512, 512, 0, PWM_ORDERED_COUNT_MINUS_ONE);
byte blue = map(xAxis * blueReverse, -512, 512, 0, PWM_ORDERED_COUNT_MINUS_ONE);

sendComboPWM(PWN_ORDERED[blue], PWN_ORDERED[red], LEGOChannel);
}

// Send blue and red PWM speed values simultaneously.
void sendComboPWM(int blue_speed, int red_speed, int channel)
{
int nib1 = COMBO_PWM_MODE | channel;
int nib2 = blue_speed;
int nib3 = red_speed;
int nib4 = 0xf ^ nib1 ^ nib2 ^ nib3;

int i;
for(i = 0; i < 6; i++)
{
message_pause(channel, i);
pf_send(nib1 << 4 | nib2, nib3 << 4 | nib4);	
}
}

// Send the power functions message. Not sure why its in two sections.
void pf_send(int code1, int code2)
{
int x = 128;

start_stop_bit();

while (x)
{
oscillationWrite();

if (code1 & x) //high bit
 high_pause();
else //low bit
 low_pause();

x >>= 1; //next bit
}

x = 128;
while (x)
{
oscillationWrite();

if (code2 & x) // high bit
 high_pause();
else //low bit
 low_pause();

x >>= 1; //next bit
}

start_stop_bit();
delay(10);
}

// See Lego IR Specifcation: LEGO Powerfunctions IR.
void start_pause()
{
delayMicroseconds(1014);
}

// See Lego IR Specifcation: LEGO Powerfunctions IR.
void high_pause()
{
delayMicroseconds(546);
}

// See Lego IR Specifcation: LEGO Powerfunctions IR.
void low_pause()
{
delayMicroseconds(260);
}

// See Lego IR Specifcation: LEGO Powerfunctions IR.
void tx_pause()
{
delayMicroseconds(156);
}

// The LEGO IR standard has a channel specific pause duration.
void message_pause(int channel, int count)
{
unsigned char a = 0;

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

delayMicroseconds(a * 77);
}

// See Lego IR Specifcation: LEGO Powerfunctions IR.
void start_stop_bit()
{
oscillationWrite();
start_pause();
}

// Flash the IR signal at the specified frequency.
void oscillationWrite()
{
for(int i = 0; i <= 6; i++)
{
digitalWrite(IRPin, HIGH);
delayMicroseconds(13);
digitalWrite(IRPin, LOW);
delayMicroseconds(13);
}
}

Edited by Bzroom
Posted

Nice work. :classic: It would be better if it was possible to put another IR led so you could transmite 2 channels at once. IE.- For a loader, have the stick for monement and the buttons for the bucket.

Posted (edited)

You can send all 4 channels through the same IR Led. Simply call sendComboPwm again with the additional channels and speeds. These parts are readily available off the shelf, so anyone can try!

Edited by Bzroom

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...