Posts with «gadget» label

IKEA SMS lamp with GSM shield

-->-->-->-->

 

 

 

We create a lamp controlled by SMS using a GSM shield, a RGB shield and a Arduino UNO.
Due to the simplicity of these boards, simply plug one over the other and connect a strip led to have a lighting effect.
Then sending normal text messages from any phone, you can turn on and choose the color to set.

The scketch check the text of the received message, if the SMS contains a character, it follows on the corresponding color.
It ‘also provided a fader functions can be called with the character F

This is the list commands:
R to set RED
G to set GREEN
B to set BLUE
Y to set YELLOW
O to set ORANGE
P to set PURPLE
W to set WHITE
F to set the fader function

This is just an example of the possible applications of the GSM / GPRS shield.
You can for example control the home lighting with a simple text message, or receive an SMS in case of alarm.
In addition, the SIM900 has the capacity to also decode DTMF tones, so you can call this in the sim GSM shield and switch loads directly from the telephone keypad.

The complete library it contains many other functions through which you can make calls, connect to the Internet, send and receive SMS.

This is the simple firmware in Arduino.

 

//GSM Shield for Arduino
//www.open-electronics.org
//this code is based on the example of Arduino Labs

#include "SIM900.h"
#include "sms.h"
#include "SoftwareSerial.h"
#include "sms.h"
SMSGSM sms;
int red = 10;    // RED LED connected to PWM pin 3
int green = 5;    // GREEN LED connected to PWM pin 5
int blue = 6;    // BLUE LED connected to PWM pin 6
int r=50; int g=100; int b=150;
int rup; int gup; int bup;

boolean started=false;
char smsbuffer[160];
char n[20];
int fader=1;
int inc=10;

void setup() 
{
  //Serial connection.
  Serial.begin(9600);
  Serial.println("GSM Shield testing.");
  //Start configuration of shield with baudrate.
  if (gsm.begin(2400)){
    Serial.println("\nstatus=READY");
    started=true;  
  }
  else Serial.println("\nstatus=IDLE");
  if(started){
    delsms();
  }

};

void loop() 
{
  int pos=0;
  //Serial.println("Loop");
  if(started){
    pos=sms.IsSMSPresent(SMS_ALL);
    if(pos){
      Serial.println("IsSMSPresent at pos ");
      Serial.println(pos); 
      sms.GetSMS(pos,n,smsbuffer,100);
        Serial.println(n);
        Serial.println(smsbuffer);
        if(!strcmp(smsbuffer,"R")){
          Serial.println("RED");
          r=255;
          g=0;
          b=0;
        }      
        if(!strcmp(smsbuffer,"G")){
          Serial.println("GREEN");
          r=0;
          g=255;
          b=0;
        }    
        if(!strcmp(smsbuffer,"B")){
          Serial.println("BLUE");
          r=0;
          g=0;
          b=255;
        }  
        if(!strcmp(smsbuffer,"P")){
          Serial.println("PURPLE");
          r=255;
          g=0;
          b=255;
        }  
        if(!strcmp(smsbuffer,"Y")){
          Serial.println("YELLOW");
          r=255;
          g=255;
          b=0;
        }  
        if(!strcmp(smsbuffer,"O")){
          Serial.println("ORANGE");
          r=255;
          g=165;
          b=0;
        }  
        if(!strcmp(smsbuffer,"W")){
          Serial.println("WHITE");
          r=255;
          g=255;
          b=255;
        }  
        if(!strcmp(smsbuffer,"F")){
          Serial.println("FADER");
          fader=1;
          r=50; g=100; b=150;
        }
        else
        {
          fader=0;
        }  
        rgb(r, g, b);
        delsms();

    }
    if(fader){
      funcfader();
    }

  }
};

void delsms(){
  Serial.println("delsms");
  for (int i=0; i<10; i++){  //do it max 10 times
      int pos=sms.IsSMSPresent(SMS_ALL);
      if (pos!=0){
        Serial.print("\nFind SMS at the pos ");
        Serial.println(pos); 
        if (sms.DeleteSMS(pos)==1){    
          Serial.print("\nDeleted SMS at the pos ");
          Serial.println(pos);      
        }
        else
        {
          Serial.print("\nCant del SMS at the pos ");
          Serial.println(pos);         
        }
      }
    }

}

void funcfader(){
    if (rup==1){r+=1;}
    else{r-=1;}
    if (r>=255){rup=0;}
    if (r<=0){rup=1;}

    if (gup==1){g+=1;}
    else{g-=1;}
    if (g>=255){gup=0;}
    if (g<=0){gup=1;}

    if (bup==1){b+=1;}
    else{b-=1;}
    if (b>=255){bup=0;}
    if (b<=0){bup=1;}  
    rgb(r, g, b);
}

void rgb(int r, int g, int b)
{
  if (r>255) r=255;
  if (g>255) g=255;
  if (b>255) b=255;
  if (r<0) r=0;
  if (g<0) g=0;
  if (b<0) b=0;

  analogWrite(red, r); 
  analogWrite(green, g); 
  analogWrite(blue, b);   
}
-->-->-->-->-->-->
-->-->

Robot shield for Arduino

-->-->-->-->

 

The idea behind this post is to bring together some robot designs and trasform them in a new device with new hardware and standard software (arduino of course) and so easier to use.  These robots have three things in common: a mechanical structure, the hardware and the software. While the mechanical part is necessarily different, we wanted to understand if there was a hardware board that could be common, with a unique development system. The choice, quite obviously, has the Arduino board, which with its development environment is perfect to create similar projects. The first consideration that came to our mind is like the Arduino board can manage a large number of servos, eight in the case of the robot SPIDER. Arduino can be powered through the plug with a voltage between 6 to 12 volts, his voltage regulator provides the 5 V stabilized, necessary for the operation of our shield. We could  power our robot with rechargeable batteries. A standard servo requires a supply voltage of 4.8 to 6 volts, easily obtainable with four batteries in series, at full charge, provide 1.5 x 4 = 6 volts but towards the complete discharge provide just 1.0 x 4 = 4 volts. We are not in optimal conditions for the servos.  Throughout this reasons we decided to create a special shield, already prepared for all these functions, it is easy to install and use.

We see now the considerations that led us to the design of this shield:

        must have a high voltage range

        will provide a stabilized output for the servos

        will provide power to the Arduino

        must be equipped with an obstacle sensor

        must have a receiver for remote control

        must read the battery

 

We can assume to power our robot with a single battery pack with a voltage between 6 and 12 volts, so for example two cells or 6-8 LiPo NiMh or NiCd cells. The servos works at 5Volt, so we should get this stabilized voltage starting from input voltage of 6-12 volts. The optimal solution is the use of a switching step-down regulator which ensures efficiency exceeding 80% in every situation.

Just the integrated LM2576-5 contains all the elements to build a switching power supply, just add an inductor, a diode and a capacitor. It can deliver a maximum current of 3A and accepts input voltages between 4 and 40volt.

 

 

Analysing the wiring diagram you can see the connector BAT which will connect the battery pack to the switch and the voltage regulator LM2576, the resistance R5 and the led LD1 are used only to detect the presence of the voltage. The stabilized voltage output from the LM2576 will be used to power all the servos, while the Arduino is powered directly from the battery pack, taking the tension just after the switch (Vin).

For reading the battery voltage will use an analog input of Arduino (A0). The two resistors R1 and R2 reduce the voltage to a value between 0 and 20 volts to a value of 0-5Volt. We chose these specific values of resistance because, by reading the analog voltage with Arduino, it is sufficient to divide the data acquired by 50 to obtain the value of the voltage in volts.

As obstacle sensor we chose the ultrasonic sensor model SRF05 that, thanks to its shape, recalls two eyes and improves the aesthetic appearance of our robot. To operate, we use a digital line connected to PIN11.

As remote control we opt for a economical infrared system; is sufficient to install an IR receiver compatible with the normal commercial remote controls, such as the integrated PNA4602. It will be sufficient a normal remote control of those used for TVs or VCRs to send commands to our robot in a simple and economic way. The shield provides the Arduino reset button, a button for general use and a LED connected to pin 13 of Arduino.

 

 

BOM

R1: 56 kohm
R2: 18 kohm
R3: 470 ohm
R4: 100 ohm
R5: 470 ohm

C1: 10 µF 63 VL
C2: 470 µF 25 VL
C3: 1000 µF 16 VL
C4: 100 nF
C5: 100 nF
C6: 10 µF 63 VL

LD1: LED 3 mm red
LD2: LED 3 mm green

U1: LM2576-5

SW1: switch

P1: Microswitch
RST: Microswitch

IR: IR38DM

L1: 100 µH 2A

D1: 1N5819

SRF05: SRF05

 

 

The Robot are three, corresponding to the robots Filippo, Bipe and Spider.

 

Filippo robot

Filippo is a biped robot whose movements are assigned to only two servos, but with this robot you can experiment with robotics without spending large sums. It is able to walk and turn around, then you can direct it in any direction, enabling those who are beginning to become familiar with the servos and how they can interact with mechanical parts. Its assembly is facilitated because all the pieces fit over each other and it is sufficient sorder to fix them permanently, as an alternative you can use the epoxy glue.

 

After the mechanical assembly, fix the Arduino board, with its shield, on top, the sensor SRF05 must look in front of the robot. The servos have to be wired as indicated in Table.

 

Connecting servos with Filippo robot

Servo

Arduino Pin Connector shiled Role
Servo 0 2 S1 Tilt (front servo)
Servo 1 3 S2 Step (servo in the bottom)


 

For the power use 6 or 8 NiCd or NiMh rechargeable batteries size AA, they should be entered in two separate holder and connected in series.  The battery holder are positioned one on the right and one on the left of the two servos, for their wiring must use two clips for batteries connected in series to 9 V.

We recommend you to program the Arduino before connecting the servos to prevent any previous program provides the wrong signals to the servos that might go crazy.

 

Program Arduino with the sketch

// FILIPPO ARDUINO
// by Segatello Mirco per ElettronicaIN 
// compilato con Arduino21

#include <Servo.h> 
#include <IRremote.h> 
#include <EEPROM.h>

#define RECV_PIN 10   // pin per sensore IR
#define PING_PIN 11   // pin per sensore RADAR
#define       P1 12   // pin per pulsante

#define STNB_CODE1 0x81D    // Stop Philips TV remote (AZIONE STOP)
#define STNB_CODE2 0x1D     // Codice alternativo
#define WALK_CODE1 0x81C    // Play Philips TV remote (AZIONE CAMMINA)
#define WALK_CODE2 0x1C     // Codice alternativo
#define SPEEDUP_CODE1 0x820 // Prg+ Philips TV remote (AZIONE PIù VELOCE)
#define SPEEDUP_CODE2 0x20  // Codice alternativo
#define SPEEDDW_CODE1 0x821 // Prg- Philips TV remote (AZIONE PIù LENTA))
#define SPEEDDW_CODE2 0x21  // Codice alternativo
#define LEFT_CODE1    0x2C  // Left Philips remote (RUOTA SX)
#define LEFT_CODE2    0x82C  // Codice alternativo
#define RIGHT_CODE1    0x2B  // Right Philips remote (ROUTA DX)
#define RIGHT_CODE2    0x82B  // Codice alternativo

#define MODE_OFF       0    // Servi OFF
#define MODE_STANDBY   1    // Servi armati in posizione di riposo
#define MODE_INWALK    2    // Assume la posizione di partenza
#define MODE_WALK      3    // Cammina in avanti
#define MODE_INSTANDBY 4    // Assume la posizione di standby
#define MODE_LEFT      5    // Si gira verso sinistra
#define MODE_RIGHT     6    // Si gira a destra
#define MODE_REVWALK   7    // Cammina all'indietro

IRrecv irrecv(RECV_PIN);
decode_results results;

int RobotMode = MODE_OFF;   
int TimeOneStep = 2000;     // Velocità di esecuzione
int AmpPasso = 30;          // Ampiezza del passo (da 5 a 40)
int IncPasso = 15;          // Inlinazione durante la camminata (da 5 a 20)
int AmpRuota = 30;          // Ampiezza delle gambe durante la rotazione (da 5 a 40)
int IncRuota = 18;          // Inclinazione durante la rotazione (da 5 a 20)

Servo servo0, servo1;       // oggetti servo

int leg_ntr[8] = {90, 90};  //posizione neutrale dei servi
int leg_old[8] = {90, 90};  //posizione precedente dei servi
int leg[8];                 //posizione attuale dei servi
int i;

void setup() 
{ 
  Serial.begin(9600);       // Start seriale
  Serial.println("FILIPPO Aduino V1.0");
  irrecv.enableIRIn();      // Start ricevitore IR  
  irrecv.blink13(true);     // Lampeggio LED in ricezione IR attivo
  pinMode(P1, INPUT);       // Pulsante 
  digitalWrite(P1, HIGH);   // Abilita pull-up
  levelBat();               // Verifica stato batteria  
  Serial.println("Livello batteria OK.");  
  Serial.println("Recupero dati posizione neutro servi...");
  readNeutral();
  Serial.println("Inizializzo Servi...");  
  initServo();              // Inizializza servi
  Serial.println("Invia 'obs' per testare il sensore di ostacoli");
  Serial.println("Invia 'lev' per testare il livello della batteria"); 
  inStandby();              // Robot in attesa di comando  
} 

void loop() 
{ 
  if (irrecv.decode(&results)) IRcommand();
  if (RobotMode==MODE_WALK)   walk();
  if (RobotMode==MODE_LEFT)   leftWalk();  
  if (RobotMode==MODE_RIGHT)   rightWalk();

  if (digitalRead(P1)==0) P1Press(); 

  if (RobotMode==MODE_STANDBY) 
  {
    if (Serial.available() > 2 )  ReceiveData();  
  }  
  else 
  {  
    // verifica livello batteria e presenza ostacoli
    levelBat();    
    int obstacle = readDistance();    
    if (obstacle < 20){
      Serial.println("Rilevato ostacolo!");   
      inStandby();  }
  }  
} 

void readNeutral()
{
  // Recupera dalla EEPROM la posizione neutrale dei servi
  byte value;
  Serial.print("Neutro dei Servi: ");      
  for (byte adress=0; adress<2; adress++) 
  {
     value = EEPROM.read(adress);
     if ((80<value) && (value<100))
     {
          leg_ntr[adress] = value;
          Serial.print(value, DEC);
          Serial.print("  ");
     }     
     else     
     {
       leg_ntr[adress] = 90;
     }  
   }
   Serial.println();
}  

void ReceiveData() 
{
    // Arrivati dati dalla USB
    byte startbyte, data_hight, data_low, data;    
    Serial.print("Receive data USB     "); 
    startbyte = Serial.read();
    data_hight = Serial.read();    
    data_low= Serial.read();
    // richiesta livello batteria
    if ( (startbyte=='l') && (data_hight=='e') && (data_low=='v'))
    {
      levelBat();     
      Serial.flush();  // svuota il buffer in ricezione  
      exit;
    }
    // richiesta distanza ostacolo
    if ( (startbyte=='o') && (data_hight=='b') && (data_low=='s'))
    {
      int obstacle = readDistance();
      Serial.print("Ostacolo a ");
      Serial.print(obstacle, DEC);    
      Serial.println(" cm");
      if (obstacle<20)  inStandby();  
      Serial.flush();  // svuota il buffer in ricezione 
      exit;
    }    
    // impostazione neutro servo
    if ((data_hight >= '0') && (data_hight <= '9') && (data_low >= '0') && (data_low <= '9')) {      
      data = (data_hight-48)*10+(data_low-48);
      if ((80 <= data) && (data <= 100)) {
         if (startbyte=='a') {
           leg_ntr[0] = data;
           EEPROM.write(0, data);
           printValue('a', data);
         }  
         if (startbyte=='b') {
           leg_ntr[1] = data;
           EEPROM.write(1, data);
           printValue('b', data);           
         }
      inStandby();         // aggiorna posizione neutro dei servi
      }
    }
    Serial.flush();  // svuota il buffer in ricezione   
}  

void printValue(byte servo, byte dt)
{
  Serial.print ("Set Servo: ");
  Serial.print (servo);
  Serial.print (" to ");
  Serial.println(dt,DEC);        
}  

void IRcommand()
{
    // E' arrivato un comando via IR
    Serial.print("IR code= ");
    Serial.println(results.value, HEX);  // ECO su serial monitor per sapere il codice arrivato

    if (results.value == WALK_CODE1 || results.value == WALK_CODE2)  inWalk();
    else if (results.value == LEFT_CODE1 || results.value == LEFT_CODE2)  inLeft();     
    else if (results.value == RIGHT_CODE1 || results.value == RIGHT_CODE2)  inRight();       
    else if (results.value == STNB_CODE1 || results.value == STNB_CODE2)  inStandby();   

    else if (results.value == SPEEDUP_CODE1 || results.value == SPEEDUP_CODE2) {
      if (TimeOneStep > 1000) TimeOneStep -= 500; }
    else if (results.value == SPEEDDW_CODE1 || results.value == SPEEDDW_CODE2) {
      if (TimeOneStep < 4000) TimeOneStep += 500; }
    Serial.print("TimeOneStep= ");      
    Serial.println(TimeOneStep);
    irrecv.resume(); // Resume decoding   
}  

void P1Press()
{
  // E' stato premuto il pulsante   
  while (digitalRead(P1)==0) delay(100);  
  if (RobotMode==MODE_WALK)  inStandby();            
  else if (RobotMode==MODE_STANDBY) inWalk(); 
}  

void levelBat()
{
  // controllo livello batteria  
  int VbatRAW = analogRead(A0);
  float Vbat = float(VbatRAW)/50;
  Serial.print("Vbat= ");
  Serial.println(Vbat, DEC);     
  if (Vbat<6.0)   {
    Serial.println("Livello batteria basso!");    
    inOff();    
  }  
}

void initServo()  
{
  // posizione iniziale dei servi
  servo0.attach(2);  // connette servo 
  delay(200);
  servo1.attach(3);  // connette servo 
  delay(200);    
  Serial.println("Servi inizializzati.");  
}

void inOff()
{
  // Spegne tutti i servi
  leg[0] = leg_ntr[0];
  leg[1] = leg_ntr[1]; 
  setServo();  
  servo0.detach();  // sconnette servo 
  servo1.detach();  // sconnette servo 
  RobotMode = MODE_OFF;     
  // Da questo modalità si deve spegnere il robot e ricaricare le batterie
}  

void inStandby()
{
  // Posiziono tutti i servi in posizione neutrale
  leg[0] = leg_ntr[0];
  leg[1] = leg_ntr[1];      
  setServo();  
  RobotMode = MODE_STANDBY;  
  Serial.println("Sono in Standby...");  
}  

void inWalk()
{
  // Si porta in posizione di passo partendo da fermo  
  leg[0] = leg_ntr[0]+IncPasso;//inclinazione
  leg[1] = leg_ntr[1];
  setServo();  

  RobotMode = MODE_WALK;
  Serial.println("Walk Mode...");   
}

void walk()
{
  // Coordinate per eseguire un passo  
  leg[0] = leg_ntr[0]+IncPasso;//piede SX in avanti
  leg[1] = leg_ntr[1]+AmpPasso;
  setServo();  

  leg[0] = leg_ntr[0]-IncPasso;//inclinazione
  leg[1] = leg_ntr[1]+AmpPasso;       
  setServo();   

  leg[0] = leg_ntr[0]-IncPasso;//passo DX
  leg[1] = leg_ntr[1]-AmpPasso;  
  setServo();

  leg[0] = leg_ntr[0]+IncPasso;//inclinazione
  leg[1] = leg_ntr[1]-AmpPasso;       
  setServo();         
}

void inLeft()
{
  // Si porta in posizione per ruotare  
  leg[0] = leg_ntr[0]+IncRuota;//inclinazione
  leg[1] = leg_ntr[1];
  setServo();         

  RobotMode = MODE_LEFT;
  Serial.println("Left Mode...");   
}

void leftWalk()
{
      //passo 1      
  leg[0] = leg_ntr[0]+IncRuota;//fa un passo
  leg[1] = leg_ntr[1]-AmpRuota;      
  setServo();        

      //passo 2      
  leg[0] = leg_ntr[0];//piedi paralleli
  leg[1] = leg_ntr[1]-AmpRuota;      
  setServo();   

      //passo 3      
  leg[0] = leg_ntr[0];//sforbiciata
  leg[1] = leg_ntr[1]+AmpRuota;     
  setServo(); 

      //passo 4      
  leg[0] = leg_ntr[0]-IncRuota;//inclinazione
  leg[1] = leg_ntr[1]+AmpRuota;     
  setServo();    

      //passo 5      
  leg[0] = leg_ntr[0]-IncRuota;//passo
  leg[1] = leg_ntr[1]-AmpRuota;     
  setServo();         

       //passo 6      
  leg[0] = leg_ntr[0];//piedi paralleli
  leg[1] = leg_ntr[1]-AmpRuota;     
  setServo();       

      //passo 7      
  leg[0] = leg_ntr[0];//sforbiciata
  leg[1] = leg_ntr[1]+AmpRuota;     
  setServo();      

      //passo 8      
  leg[0] = leg_ntr[0]+IncRuota;//sforbiciata
  leg[1] = leg_ntr[1]+AmpRuota;     
  setServo();     
}

void inRight()
{  
  // Si porta in posizione per ruotare  
      //passo 0  inclinazione
  leg[0] = leg_ntr[0]+IncRuota;
  leg[1] = leg_ntr[1];
  setServo();         

  RobotMode = MODE_RIGHT;
  Serial.println("Right Mode...");   
}

void rightWalk()
{
      //passo 1  passo    
  leg[0] = leg_ntr[0]+IncRuota;
  leg[1] = leg_ntr[1]+AmpRuota;      
  setServo();        

      //passo 2 piedi paralleli     
  leg[0] = leg_ntr[0];
  leg[1] = leg_ntr[1]+AmpRuota;      
  setServo();   

      //passo 3  sforbiciata    
  leg[0] = leg_ntr[0];
  leg[1] = leg_ntr[1]-AmpRuota;     
  setServo();

      //passo 4 inclinazione     
  leg[0] = leg_ntr[0]-IncRuota;
  leg[1] = leg_ntr[1]-AmpRuota;     
  setServo();    

      //passo 5  passo    
  leg[0] = leg_ntr[0]-IncRuota;
  leg[1] = leg_ntr[1]+AmpRuota;     
  setServo();         

       //passo 6 piedi paralleli     
  leg[0] = leg_ntr[0];
  leg[1] = leg_ntr[1]+AmpRuota;     
  setServo();       

      //passo 7 sforbiciata
  leg[0] = leg_ntr[0];
  leg[1] = leg_ntr[1]-AmpRuota;     
  setServo();         

      //passo 8 inclinazione     
  leg[0] = leg_ntr[0]+IncRuota;
  leg[1] = leg_ntr[1]-AmpRuota;     
  setServo();   
} 

void setServo() 
{  
   // Posiziona i servi alle coordinate specificate da leg[]  
   for (i=0; i<18; i++) {
       servo0.write(leg_old[0] + i*(leg[0]-leg_old[0])/18);  
       servo1.write(leg_old[1] + i*(leg[1]-leg_old[1])/18);        
       delay(TimeOneStep/4/18);
    }   
    leg_old[0]=leg[0];
    leg_old[1]=leg[1];       
}

long readDistance()
{
  // Procedura per leggere la presenza di ostacoli
  // Viene generato un PING di 2usec ed atteso l'ECO di risposta
  long duration, cm;
  pinMode(PING_PIN, OUTPUT);
  digitalWrite(PING_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(PING_PIN, HIGH);
  delayMicroseconds(5);
  digitalWrite(PING_PIN, LOW);

  // Lo stesso pin che genera il trigger è usato per la lettura
  // del segnale di ritorno
  pinMode(PING_PIN, INPUT);
  duration = pulseIn(PING_PIN, HIGH);

  // ritorna distanza ostacolo in cm
  return duration / 29 / 2;
}

Send the serial command ‘obs‘ for read the sensor SRF05 and the command ‘lev‘ to check the battery level. Make sure that the voltage read corresponds to the real value of the batteries, simply make a voltage measurement with a multimeter. Now set the neutral of the servos, in fact the robot to function properly must be perfectly centered. To center the servo which acts to tilt the robot you have to send the command ‘axx‘ where xx is the position. This data can assume values between 80 and 100 with the center point 90, if you can not set the servo to remain within these values you have to physically move the servo. You can modify this value if it found a tendency to deviate from the straight line when walking. Now regulate the step servo and sets the neutral with bxx command, where xx is the position to be allocated (value between 80 and 100). You are now ready for test, you can use the remote control to activate functions or use the button on the shield but it will only start the walk.

 

All functions have a speed of execution that can be changed by remote control with keys prog+ and prog-, many other parameters can be modified to adapt the software to different operating requirements.

The sketch begins by including the libraries dedicated to the use of the servos, the IR control and management of EEPROM:

 

Code 1

#include <Servo.h>
#include <IRremote.h>
#include <EEPROM.h>

 

The servo library is already implemented in the IDE of Arduino.

The EEPROM library, also available, provides controls to manage the non-volatile memory, we use it to save the position of the neutral servos so as not having to set each time.

The third library IRremote is used to manage the robot by remote control and must be downloaded from http://github.com/shirriff/Arduino-IRremote, for its operation is sufficient to specify which pin is connected to the sensor receiving IR signals (D10 in our shield). To find out if they arrived from the sensor data must test the status of the variable irrecv.decode (& results), but the code is contained in the variable came results.value.

Just compare the code recived with the reference code for the remote to know which button was pressed, so we specify at the beginning of the sketch of the codes for each button.

 

Code 2

#define STNB_CODE1 0x81D    // Stop Philips TV remote (STOP)
#define STNB_CODE2 0x1D     // alternative code
#define WALK_CODE1 0x81C    // Play Philips TV remote (WALK)
#define WALK_CODE2 0x1C // alternative code
#define SPEEDUP_CODE1 0x820 // Prg+ Philips TV remote (+ SPEED)
#define SPEEDUP_CODE2 0x20  // alternative code
#define SPEEDDW_CODE1 0x821 // Prg- Philips TV remote (-SPEED)
#define SPEEDDW_CODE2 0x21  // alternative code
#define LEFT_CODE1    0x2C  // Left Philips remote (SX wheel)
#define LEFT_CODE2    0x82C  // alternative code
#define RIGHT_CODE1    0x2B  // Right Philips remote (DX wheel)
#define RIGHT_CODE2    0x82B  // alternative code

 

As you can see each button is associated with two codes (CODE1 and CODE2) this is because the codes are sent alternately every time you press the button, instead of repeating the same code if the button is pressed. So if you press the play button will send the code 0x81C and so long as the button is pressed, if you release the button and press it sends the code 0x1C, so alternately.

The sketch is intended for use with remote controls which use the encoding Philips, the most commonly used in television. If you use a different remote control the code of the buttons do not match and you have to change the codes listed above.

Now let’s see what parameters can be modified by the program to adapt the movements:

 

Code 3

int TimeOneStep = 2000;    
int AmpPasso = 30;         
int IncPasso = 15;         
int AmpRuota = 30;       
int IncRuota = 18;

 

 

TimeOneStep is the initial value of the time taken to perform a step, can be changed by remote control from a minimum of 1 sec to a maximum of 4 sec.

AmpPasso is the maximum amplitude in degrees of opening of the legs during walking, its value can vary from a minimum of 5 to a maximum of 40.

IncPasso is the maximum inclination of the robot during the walk, its value can vary from a minimum of 5 to a maximum of 20. This value is to ensure the robot to keep balance on one leg while performing a step.

AmpRuota is the maximum amplitude in degrees of opening of the legs during the rotation, its value can change from a minimum of 5 to a maximum of 40.

IncRuota is the maximum inclination of the robot during the rotation, its value can change from a minimum of 5 to a maximum of 20.

 

 

ROBOT BIPE

We see now to the second robot, is called BIPE.

The mechanical is made of PCB and assembly is made by soding together the various components to ensure the strength needed to support the weight of the components.

The control board based on Arduino + shield is positioned on the back of the robot while the battery pack, should be placed at the front. Let’s say that for our tests we used a battery composed of two cell 850mAh LiPo which, being small and light, are easily placed and not weigh down the structure. To properly position the sensor SRF05 you must use a small adapter with a strip made of male-female, as those used on the Arduino shield, angled 90 °.

Connecting servos with robot BIPE

Servo Arduino Pin Connector shield Function
Servo 0 2 S1 left hip
Servo 1 3 S2 left knee
Servo 2 4 S3 left foot
Servo 3 5 S4 right hip
Servo 4 6 S5 right knee
Servo 5 7 S6 right foot

 

For setting follow the same instructions for the robot Filippo, the sketch retains the same structure of the software used with Filippo, with the necessary modifications and add.

 

// BIPE ARDUINO
// by Segatello Mirco per ElettronicaIN 
// compilato con Arduino21

#include <Servo.h> 
#include <IRremote.h> 
#include <EEPROM.h>

#define RECV_PIN 10   // pin per sensore IR
#define PING_PIN 11   // pin per sensore RADAR
#define       P1 12   // pin per pulsante

#define STNB_CODE1 0x81D    // Stop Philips TV remote
#define STNB_CODE2 0x1D     // Codice alternativo
#define WALK_CODE1 0x81C    // Play Philips TV remote
#define WALK_CODE2 0x1C     // Codice alternativo
#define SPEEDUP_CODE1 0x820 // Prg+ Philips TV remote
#define SPEEDUP_CODE2 0x20  // Codice alternativo
#define SPEEDDW_CODE1 0x821 // Prg- Philips TV remote
#define SPEEDDW_CODE2 0x21  // Codice alternativo
#define LEFT_CODE1    0x2C  // Left Philips remote
#define LEFT_CODE2    0x82C  // Codice alternativo
#define RIGHT_CODE1    0x2B  // Right Philips remote
#define RIGHT_CODE2    0x82B  // Codice alternativo
#define VOLUP_CODE1   0x810 // Volume+
#define VOLUP_CODE2   0x10  // codice alternativo
#define VOLDW_CODE1   0x811 //Volume-
#define VOLDW_CODE2   0x11 //codice alternativo

#define PRG1_CODE1 0x801 // Program 1
#define PRG1_CODE2 0x1 // Program 1
#define PRG2_CODE1 0x802 // Program 2
#define PRG2_CODE2 0x2 // Program 2

#define MODE_OFF       0    // Servi OFF
#define MODE_STANDBY   1    // Servi armati in posizione di riposo
#define MODE_INWALK    2    // Assume la posizione di partenza
#define MODE_WALK      3    // Cammina in avanti
#define MODE_INSTANDBY 4    // Assume la posizione di standby
#define MODE_LEFT      5    // Si gira verso sinistra
#define MODE_RIGHT     6    // Si gira a destra
#define MODE_REVWALK   7    // Cammina all'indietro

IRrecv irrecv(RECV_PIN);
decode_results results;

int RobotMode = MODE_OFF;   
int TimeOneStep = 4000;     // Velocità di esecuzione
int AmpPasso = 10;          // Ampiezza del passo (da 5 a 20)
int AmpRuota = 12;          // Ampiezza durante la rotazione (da 5 a 20)
int IncPasso = 8;           // Inlinazione durante la camminata (da 5 a 10)

Servo servo0, servo1, servo2, servo3,
      servo4, servo5, servo6, servo7;  // oggetti servo
      // Servo 6 e 7 possono essere usati per le braccia!

int leg_ntr[8] = {90, 90, 90, 90, 90, 90, 90, 90}; //posizione neutrale dei servi
int leg_old[8] = {90, 90, 90, 90, 90, 90, 90, 90}; //posizione precedente dei servi
int leg[8];                 //posizione attuale dei servi
int i;

void setup() 
{ 
  Serial.begin(9600);       // Start seriale
  Serial.println("SIDERIN Aduino V1.0");
  irrecv.enableIRIn();      // Start ricevitore IR  
  irrecv.blink13(true);     // Lampeggio LED in ricezione IR attivo
  pinMode(P1, INPUT);       // Pulsante 
  digitalWrite(P1, HIGH);   // Abilita pull-up
  levelBat();               // Verifica stato batteria  
  Serial.println("Livello batteria OK.");  
  Serial.println("Recupero dati posizione neutro servi...");
  readNeutral();
  Serial.println("Inizializzo Servi...");  
  initServo();              // Inizializza servi
  Serial.println("Invia 'obs' per testare il sensore di ostacoli");
  Serial.println("Invia 'lev' per testare il livello della batteria"); 
  inStandby();              // Robot in attesa di comando  
} 

void loop() 
{ 
  if (irrecv.decode(&results)) IRcommand();
  if (RobotMode==MODE_WALK)   walk();
//  if (RobotMode==MODE_REVWALK) walkReverse();
  if (RobotMode==MODE_LEFT)   leftWalk();  
  if (RobotMode==MODE_RIGHT)   rightWalk();

  if (digitalRead(P1)==0) P1Press(); 

  if (RobotMode==MODE_STANDBY) 
  {
    if (Serial.available() > 2 )  ReceiveData();  
  }  
  else 
  {  
    levelBat();    
    int obstacle = readDistance();    
    if (obstacle < 20)  inStandby();  
  }  
} 

void readNeutral()
{
  // Recupera dalla EEPROM la posizione neutrale dei servi
  byte value;
  Serial.print("Neutro dei Servi: ");      
  for (byte adress=0; adress<6; adress++) 
  {
     value = EEPROM.read(adress);
     if ((80<value) && (value<100))
     {
          leg_ntr[adress] = value;
          Serial.print(value, DEC);
          Serial.print("  ");
     }     
     else     
     {
       leg_ntr[adress] = 90;
     }  
   }
   Serial.println();
}  

void ReceiveData() 
{
    // Arrivati dati dalla USB
    byte startbyte, data_hight, data_low, data;    
    Serial.print("Receive data USB     "); 
    startbyte = Serial.read();
    data_hight = Serial.read();    
    data_low= Serial.read();
    // richiesta livello batteria
    if ( (startbyte=='l') && (data_hight=='e') && (data_low=='v'))
    {
      levelBat();     
      Serial.flush();  // svuota il buffer in ricezione  
      exit;
    }
    // richiesta distanza ostacolo
    if ( (startbyte=='o') && (data_hight=='b') && (data_low=='s'))
    {
      int obstacle = readDistance();
      Serial.print("Ostacolo a ");
      Serial.print(obstacle, DEC);    
      Serial.println(" cm");
      if (obstacle<20)  inStandby();  
      Serial.flush();  // svuota il buffer in ricezione 
      exit;
    }    
    // impostazione neutro servo
    if ((data_hight >= '0') && (data_hight <= '9') && (data_low >= '0') && (data_low <= '9')) {      
      data = (data_hight-48)*10+(data_low-48);
      if ((80 <= data) && (data <= 100)) {
         if (startbyte=='a') {
           leg_ntr[0] = data;
           EEPROM.write(0, data);
           printValue('a', data);
         }  
         if (startbyte=='b') {
           leg_ntr[1] = data;
           EEPROM.write(1, data);
           printValue('b', data);           
         }
         if (startbyte=='c') {
           leg_ntr[2] = data;
           EEPROM.write(2, data);
           printValue('c', data);                  
         }  
         if (startbyte=='d') {
           leg_ntr[3] = data;
           EEPROM.write(3, data);
           printValue('d', data);                    
         }  
         if (startbyte=='e') {
           leg_ntr[4] = data;
           EEPROM.write(4, data);
           printValue('e', data);                   
         }
         if (startbyte=='f') {
           leg_ntr[5] = data;
           EEPROM.write(5, data);
           printValue('f', data);                   
         }
      inStandby();         // aggiorna posizione neutro dei servi
      }
    }
    Serial.flush();  // svuota il buffer in ricezione   
}  

void printValue(byte servo, byte dt)
{
  Serial.print ("Set Servo: ");
  Serial.print (servo);
  Serial.print (" to ");
  Serial.println(dt,DEC);        
}  

void IRcommand()
{
    // E' arrivato un comando via IR
    Serial.println(results.value, HEX);  // ECO su serial monitor per sapere il codice arrivato

    if (results.value == WALK_CODE1 || results.value == WALK_CODE2)   inWalk();     
    else if (results.value == LEFT_CODE1 || results.value == LEFT_CODE2)  inLeft();     
    else if (results.value == RIGHT_CODE1 || results.value == RIGHT_CODE2)  inRight();       
    else if (results.value == STNB_CODE1 || results.value == STNB_CODE2)  inStandby();   

    else if (results.value == PRG1_CODE1 || results.value == PRG1_CODE2) {
      if (RobotMode==MODE_STANDBY) kick(); }

    else if (results.value == PRG2_CODE1 || results.value == PRG2_CODE2)  {
       if (RobotMode==MODE_STANDBY)  bow(); }

    else if (results.value == SPEEDUP_CODE1 || results.value == SPEEDUP_CODE2) {
      if (TimeOneStep > 1000) TimeOneStep -= 200; }
    else if (results.value == SPEEDDW_CODE1 || results.value == SPEEDDW_CODE2) {
      if (TimeOneStep < 2000) TimeOneStep += 200; }
    Serial.print("TimeOneStep= ");      
    Serial.println(TimeOneStep);
    irrecv.resume(); // Resume decoding   
}  

void P1Press()
{
  // E' stato premuto il pulsante   
  while (digitalRead(P1)==0) delay(100);  
  if (RobotMode==MODE_WALK)  inStandby();            
  else if (RobotMode==MODE_STANDBY) inWalk(); 
}  

void levelBat()
{
  // controllo livello batteria  
  int VbatRAW = analogRead(A0);
  float Vbat = float(VbatRAW)/50;
  Serial.print("Vbat= ");
  Serial.println(Vbat, DEC);     
  if (Vbat<6.0)   {
    Serial.println("Livello batteria basso!");    
    inOff();    
  }  
}

void initServo()  
{
  // posizione iniziale dei servi
  servo0.attach(2);  // connette servo 
  delay(200);
  servo1.attach(3);  // connette servo 
  delay(200);  
  servo2.attach(4);  // connette servo 
  delay(200);
  servo3.attach(5);  // connette servo 
  delay(200);  
  servo4.attach(6);  // connette servo 
  delay(200);
  servo5.attach(7);  // connette servo 
  delay(200);  
  servo6.attach(8);  // connette servo 
  delay(200);
  servo7.attach(9);  // connette servo 
  delay(200);  
  Serial.println("Servi inizializzati.");  
}

void inOff()
{
  // Spegne tutti i servi
  leg[0] = leg_ntr[0];
  leg[1] = leg_ntr[1];
  leg[2] = leg_ntr[2];
  leg[3] = leg_ntr[3];
  leg[4] = leg_ntr[4];
  leg[5] = leg_ntr[5];   
  leg[6] = 90;
  leg[7] = 90;    
  setServo();  
  servo0.detach();  // sconnette servo 
  servo1.detach();  // sconnette servo 
  servo2.detach();  // sconnette servo 
  servo3.detach();  // sconnette servo 
  servo4.detach();  // sconnette servo 
  servo5.detach();  // sconnette servo 
  servo6.detach();  // sconnette servo 
  servo7.detach();  // sconnette servo   
  RobotMode = MODE_OFF;     
  // Da questo modalità si deve spegnere il robot e ricaricare le batterie
}  

void inStandby()
{
  // Posiziono tutti i servi in posizione neutrale
  leg[0] = leg_ntr[0];
  leg[1] = leg_ntr[1];
  leg[2] = leg_ntr[2];
  leg[3] = leg_ntr[3];
  leg[4] = leg_ntr[4];
  leg[5] = leg_ntr[5];
  leg[6] = 90;
  leg[7] = 90;      
  setServo();  
  RobotMode = MODE_STANDBY;  
  Serial.println("Sono in Standby...");  
}  

void inWalk()
{
  // Si porta in posizione di passo partendo da fermo  
  leg[0] = leg_ntr[0];//inclinazione
  leg[1] = leg_ntr[1];
  leg[2] = leg_ntr[2]-IncPasso;
  leg[3] = leg_ntr[3];
  leg[4] = leg_ntr[4];
  leg[5] = leg_ntr[5]-IncPasso*2;  
  setServo();    
  leg[0] = leg_ntr[0]+AmpPasso;//passo DX da fermo
  leg[1] = leg_ntr[1]+AmpPasso;
  leg[2] = leg_ntr[2]-IncPasso;
  leg[3] = leg_ntr[3]+AmpPasso;
  leg[4] = leg_ntr[4]+AmpPasso;
  leg[5] = leg_ntr[5]-IncPasso*2;      
  setServo();
  RobotMode = MODE_WALK;
  Serial.println("Walk Mode...");   
}

void setServo() 
{  
   // Posiziona i servi alle coordinate specificate da leg[]  
   for (i=0; i<18; i++) {
       servo0.write(leg_old[0] + i*(leg[0]-leg_old[0])/18);  
       servo1.write(leg_old[1] + i*(leg[1]-leg_old[1])/18);        
       servo2.write(leg_old[2] + i*(leg[2]-leg_old[2])/18);  
       servo3.write(leg_old[3] + i*(leg[3]-leg_old[3])/18);      
       servo4.write(leg_old[4] + i*(leg[4]-leg_old[4])/18);  
       servo5.write(leg_old[5] + i*(leg[5]-leg_old[5])/18);        
       servo6.write(leg_old[6] + i*(leg[6]-leg_old[6])/18);  
       servo7.write(leg_old[7] + i*(leg[7]-leg_old[7])/18);    
       delay(TimeOneStep/4/18);
    }   
    leg_old[0]=leg[0];
    leg_old[1]=leg[1]; 
    leg_old[2]=leg[2];
    leg_old[3]=leg[3];  
    leg_old[4]=leg[4];
    leg_old[5]=leg[5]; 
    leg_old[6]=leg[6];
    leg_old[7]=leg[7];       
}  

void      setServoWalk()
{
};   

void walk()
{
  // Coordinate per eseguire un passo
  leg[0] = leg_ntr[0]+AmpPasso;//inclinazione
  leg[1] = leg_ntr[1]+AmpPasso;
  leg[2] = leg_ntr[2]+IncPasso*2;
  leg[3] = leg_ntr[3]+AmpPasso;
  leg[4] = leg_ntr[4]+AmpPasso;
  leg[5] = leg_ntr[5]+IncPasso;       
  setServo();  
  if (RobotMode!=MODE_WALK) return;  

  leg[0] = leg_ntr[0]-AmpPasso;//passo SX
  leg[1] = leg_ntr[1]-AmpPasso;
  leg[2] = leg_ntr[2]+IncPasso*2;
  leg[3] = leg_ntr[3]-AmpPasso;
  leg[4] = leg_ntr[4]-AmpPasso;
  leg[5] = leg_ntr[5]+IncPasso;  
  setServo();
  if (RobotMode!=MODE_WALK) return;

  leg[0] = leg_ntr[0]-AmpPasso;//inclinazione
  leg[1] = leg_ntr[1]-AmpPasso;
  leg[2] = leg_ntr[2]-IncPasso;
  leg[3] = leg_ntr[3]-AmpPasso;
  leg[4] = leg_ntr[4]-AmpPasso;
  leg[5] = leg_ntr[5]-IncPasso*2;  
  setServo();
  if (RobotMode!=MODE_WALK) return;

  leg[0] = leg_ntr[0]+AmpPasso;//passo DX
  leg[1] = leg_ntr[1]+AmpPasso;
  leg[2] = leg_ntr[2]-IncPasso;
  leg[3] = leg_ntr[3]+AmpPasso;
  leg[4] = leg_ntr[4]+AmpPasso;
  leg[5] = leg_ntr[5]-IncPasso*2;      
  setServo();        
}

void inLeft()
{
  // Si posiziona pronto per girare a sinistra   
  leg[0] = leg_ntr[0];//inclinazione SX
  leg[1] = leg_ntr[1];
  leg[2] = leg_ntr[2]-IncPasso;
  leg[3] = leg_ntr[3];
  leg[4] = leg_ntr[4];
  leg[5] = leg_ntr[5]-IncPasso*2;    
  setServo();    

  leg[0] = leg_ntr[0];//piede DX avanti
  leg[1] = leg_ntr[1];
  leg[2] = leg_ntr[2]-IncPasso;
  leg[3] = leg_ntr[3]+AmpRuota;
  leg[4] = leg_ntr[4]+AmpRuota;
  leg[5] = leg_ntr[5]-IncPasso*2;       
  setServo(); 

  leg[0] = leg_ntr[0];//inclinazione DX
  leg[1] = leg_ntr[1];
  leg[2] = leg_ntr[2]+IncPasso*2;
  leg[3] = leg_ntr[3]+AmpRuota;
  leg[4] = leg_ntr[4]+AmpRuota;
  leg[5] = leg_ntr[5]+IncPasso;        
  setServo();

  leg[0] = leg_ntr[0]+AmpRuota;//piede SX indietro
  leg[1] = leg_ntr[1]+AmpRuota;
  leg[2] = leg_ntr[2]+IncPasso*2;
  leg[3] = leg_ntr[3]+AmpRuota;
  leg[4] = leg_ntr[4]+AmpRuota;
  leg[5] = leg_ntr[5]+IncPasso;      
  setServo();     

  leg[0] = leg_ntr[0]+AmpRuota;//piedi a terra
  leg[1] = leg_ntr[1]+AmpRuota;
  leg[2] = leg_ntr[2];
  leg[3] = leg_ntr[3]+AmpRuota;
  leg[4] = leg_ntr[4]+AmpRuota;
  leg[5] = leg_ntr[5];      
  setServo();       

  RobotMode = MODE_LEFT;
  Serial.println("Left Mode...");   
}

void leftWalk()
{
      //passo 1      
  leg[0] = leg_ntr[0]-AmpRuota;//sforbiciata
  leg[1] = leg_ntr[1]-AmpRuota;
  leg[2] = leg_ntr[2];
  leg[3] = leg_ntr[3]-AmpRuota;
  leg[4] = leg_ntr[4]-AmpRuota;
  leg[5] = leg_ntr[5];      
  setServo();       
      if (RobotMode!=MODE_LEFT) return;   

      //passo 2      
  leg[0] = leg_ntr[0]-AmpRuota;//inclinazione
  leg[1] = leg_ntr[1]-AmpRuota;
  leg[2] = leg_ntr[2]-IncPasso;
  leg[3] = leg_ntr[3]-AmpRuota;
  leg[4] = leg_ntr[4]-AmpRuota;
  leg[5] = leg_ntr[5]-IncPasso*2;      
  setServo();   
      if (RobotMode!=MODE_LEFT) return;

      //passo 3      
  leg[0] = leg_ntr[0]-AmpRuota;//sposta piede DX in avanti
  leg[1] = leg_ntr[1]-AmpRuota;
  leg[2] = leg_ntr[2]-IncPasso;
  leg[3] = leg_ntr[3]+AmpRuota;
  leg[4] = leg_ntr[4]+AmpRuota;
  leg[5] = leg_ntr[5]-IncPasso*2;      
  setServo();
      if (RobotMode!=MODE_LEFT) return; 

      //passo 4      
  leg[0] = leg_ntr[0]-AmpRuota;//inclinazione
  leg[1] = leg_ntr[1]-AmpRuota;
  leg[2] = leg_ntr[2]+IncPasso*2;
  leg[3] = leg_ntr[3]+AmpRuota;
  leg[4] = leg_ntr[4]+AmpRuota;
  leg[5] = leg_ntr[5]+IncPasso;      
  setServo();
      if (RobotMode!=MODE_LEFT) return;

      //passo 5      
  leg[0] = leg_ntr[0]+AmpRuota;//sposta SX indietro
  leg[1] = leg_ntr[1]+AmpRuota;
  leg[2] = leg_ntr[2]+IncPasso*2;
  leg[3] = leg_ntr[3]+AmpRuota;
  leg[4] = leg_ntr[4]+AmpRuota;
  leg[5] = leg_ntr[5]+IncPasso;      
  setServo();
      if (RobotMode!=MODE_LEFT) return;

      //passo 6
  leg[0] = leg_ntr[0]+AmpRuota;//piedi a terra
  leg[1] = leg_ntr[1]+AmpRuota;
  leg[2] = leg_ntr[2];
  leg[3] = leg_ntr[3]+AmpRuota;
  leg[4] = leg_ntr[4]+AmpRuota;
  leg[5] = leg_ntr[5];      
  setServo();  
     if (RobotMode!=MODE_LEFT) return;
}

void inRight()
{
  // Si posiziona pronto per girare a sinistra   
  leg[0] = leg_ntr[0];//inclinazione SX
  leg[1] = leg_ntr[1];
  leg[2] = leg_ntr[2]+IncPasso*2;
  leg[3] = leg_ntr[3];
  leg[4] = leg_ntr[4];
  leg[5] = leg_ntr[5]+IncPasso;    
  setServo();    

  leg[0] = leg_ntr[0]-AmpRuota;//piede DX avanti
  leg[1] = leg_ntr[1]-AmpRuota;
  leg[2] = leg_ntr[2]+IncPasso*2;
  leg[3] = leg_ntr[3];
  leg[4] = leg_ntr[4];
  leg[5] = leg_ntr[5]+IncPasso;       
  setServo(); 

  leg[0] = leg_ntr[0]-AmpRuota;//inclinazione DX
  leg[1] = leg_ntr[1]-AmpRuota;
  leg[2] = leg_ntr[2]-IncPasso;
  leg[3] = leg_ntr[3];
  leg[4] = leg_ntr[4];
  leg[5] = leg_ntr[5]-IncPasso*2;        
  setServo();

  leg[0] = leg_ntr[0]-AmpRuota;//piede SX indietro
  leg[1] = leg_ntr[1]-AmpRuota;
  leg[2] = leg_ntr[2]-IncPasso;
  leg[3] = leg_ntr[3]-AmpRuota;
  leg[4] = leg_ntr[4]-AmpRuota;
  leg[5] = leg_ntr[5]-IncPasso*2;      
  setServo();     

  leg[0] = leg_ntr[0]-AmpRuota;//piedi a terra
  leg[1] = leg_ntr[1]-AmpRuota;
  leg[2] = leg_ntr[2];
  leg[3] = leg_ntr[3]-AmpRuota;
  leg[4] = leg_ntr[4]-AmpRuota;
  leg[5] = leg_ntr[5];      
  setServo();       

  RobotMode = MODE_RIGHT;
  Serial.println("Right Mode...");   
}

void rightWalk()
{
      //passo 1      
  leg[0] = leg_ntr[0]+AmpRuota;//sforbiciata
  leg[1] = leg_ntr[1]+AmpRuota;
  leg[2] = leg_ntr[2];
  leg[3] = leg_ntr[3]+AmpRuota;
  leg[4] = leg_ntr[4]+AmpRuota;
  leg[5] = leg_ntr[5];      
  setServo();       
      if (RobotMode!=MODE_RIGHT) return;   

      //passo 2      
  leg[0] = leg_ntr[0]+AmpRuota;//inclinazione
  leg[1] = leg_ntr[1]+AmpRuota;
  leg[2] = leg_ntr[2]+IncPasso*2;
  leg[3] = leg_ntr[3]+AmpRuota;
  leg[4] = leg_ntr[4]+AmpRuota;
  leg[5] = leg_ntr[5]+IncPasso;      
  setServo();   
      if (RobotMode!=MODE_RIGHT) return;

      //passo 3      
  leg[0] = leg_ntr[0]+AmpRuota;//sposta piede DX in avanti
  leg[1] = leg_ntr[1]+AmpRuota;
  leg[2] = leg_ntr[2]+IncPasso*2;
  leg[3] = leg_ntr[3]-AmpRuota;
  leg[4] = leg_ntr[4]-AmpRuota;
  leg[5] = leg_ntr[5]+IncPasso;      
  setServo();
      if (RobotMode!=MODE_RIGHT) return; 

      //passo 4      
  leg[0] = leg_ntr[0]+AmpRuota;//inclinazione
  leg[1] = leg_ntr[1]+AmpRuota;
  leg[2] = leg_ntr[2]-IncPasso;
  leg[3] = leg_ntr[3]-AmpRuota;
  leg[4] = leg_ntr[4]-AmpRuota;
  leg[5] = leg_ntr[5]-IncPasso*2;      
  setServo();
      if (RobotMode!=MODE_RIGHT) return;

      //passo 5      
  leg[0] = leg_ntr[0]-AmpRuota;//sposta SX indietro
  leg[1] = leg_ntr[1]-AmpRuota;
  leg[2] = leg_ntr[2]-IncPasso;
  leg[3] = leg_ntr[3]-AmpRuota;
  leg[4] = leg_ntr[4]-AmpRuota;
  leg[5] = leg_ntr[5]-IncPasso*2;      
  setServo();
      if (RobotMode!=MODE_RIGHT) return;

      //passo 6
  leg[0] = leg_ntr[0]-AmpRuota;//piedi a terra
  leg[1] = leg_ntr[1]-AmpRuota;
  leg[2] = leg_ntr[2];
  leg[3] = leg_ntr[3]-AmpRuota;
  leg[4] = leg_ntr[4]-AmpRuota;
  leg[5] = leg_ntr[5];      
  setServo();         
      if (RobotMode!=MODE_RIGHT) return;  
} 

void bow()
{
  //inchino
  leg[0] = leg_ntr[0]-60;
  leg[1] = leg_ntr[1]-10;
  leg[2] = leg_ntr[2];
  leg[3] = leg_ntr[3]+60;
  leg[4] = leg_ntr[4]+10;
  leg[5] = leg_ntr[5];  
  setServo();    
  delay(1000);
  leg[0] = leg_ntr[0];//passo DX da fermo
  leg[1] = leg_ntr[1];
  leg[2] = leg_ntr[2];
  leg[3] = leg_ntr[3];
  leg[4] = leg_ntr[4];
  leg[5] = leg_ntr[5];      
  setServo();    
}  

void kick()
{
   //calcio 
  leg[0] = leg_ntr[0];//inclinazione
  leg[1] = leg_ntr[1];
  leg[2] = leg_ntr[2]-12;//regolare questo valore per bilanciare
  leg[3] = leg_ntr[3];
  leg[4] = leg_ntr[4];
  leg[5] = leg_ntr[5]-24;  
  setServo();    
  leg[0] = leg_ntr[0];//piede indietro
  leg[1] = leg_ntr[1];
  leg[2] = leg_ntr[2]-12;//regolare questo valore per bilanciare
  leg[3] = leg_ntr[3]-AmpPasso;
  leg[4] = leg_ntr[4]+AmpPasso;
  leg[5] = leg_ntr[5];  
  setServo();       
  //calcia 

       leg_old[3]=leg_ntr[3]+AmpPasso; 
       servo3.write(leg_old[3]);      
       leg_old[4]=leg_ntr[4]-AmpPasso;        
       servo4.write(leg_old[4]);  

  leg[0] = leg_ntr[0];//ritorna in posizione
  leg[1] = leg_ntr[1];
  leg[2] = leg_ntr[2];
  leg[3] = leg_ntr[3];
  leg[4] = leg_ntr[4];
  leg[5] = leg_ntr[5];      
  setServo();  

}  

long readDistance()
{
  // Procedura per leggere la presenza di ostacoli
  // Viene generato un PING di 2usec ed atteso l'ECO di risposta
  long duration, cm;
  pinMode(PING_PIN, OUTPUT);
  digitalWrite(PING_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(PING_PIN, HIGH);
  delayMicroseconds(5);
  digitalWrite(PING_PIN, LOW);

  // Lo stesso pin che genera il trigger è usato per la lettura
  // del segnale di ritorno
  pinMode(PING_PIN, INPUT);
  duration = pulseIn(PING_PIN, HIGH);

  // ritorna distanza ostacolo in cm
  return duration / 29 / 2;
}

 

For this robot is important to the calibration of the neutral of the servos that occurs as previously described.  Servo0 corresponds to the letter ‘a‘ – Servo5 corresponds to the letter ‘f‘. If the command is ok will receive confirmation of Serial Monitor, for example: “set servo: a to 90“.

 

 

 

 

This robot have additional functions such as the bow and football features that are not implemented on Filippo.

 

Code 4

#define PRG1_CODE1 0x801 // Program 1
#define PRG1_CODE2 0x1 // Program 1
#define PRG2_CODE1 0x802 // Program 2
#define PRG2_CODE2 0x2 // Program 2

 

To the button ’1 ‘corresponds to the function of football with which the robot can hit, for example a ball, to the button ’2′ corresponds to the bow that is always of great effect.

The parameters can be set by the program are similar to those of robot Filippo:

 

Code 5

int TimeOneStep = 4000;  
int AmpPasso = 10;         
int AmpRuota = 12;         
int IncPasso = 8;

 

SPIDER ROBOT

With this robot we wanted to replicate the appearance and movements of a spider with all the limitations derived from a simplified mechanics and a limited cost.  The choice has been the use of two servos for paw for a total of four legs, which, however, ensure a final result very attractive. The largest number of servos relative to the robot BIPE should not scare because, at the end, this robot is the most simple to make and having regard to the intrinsic stability, does not present serious problems even in the operation. For this robot we have not even provided the adjustment of the neutral servos because of some inaccuracies should not be to influence the operation.The only care is to fix the battery pack in the center so the robots present the center of gravity exactly in the center. During the movement three legs always remain in contact with the ground while one moves, rising, thereby ensuring a good stability.

The mechanical is made by PCB, the same material used for printed electronic and suggest paint it black to improve the aesthetic appearance. No soldering required, and each piece is simply screwed to the servos that make up the mechanics.

How practical advice suggest to program the Arduino board with this program and then electrically connecting the servos, doing so will all be positioned exactly in the middle.Then you connect the mechanical servos in their proper locations.

// SPIDER ARDUINO
// by Segatello Mirco for ElettronicaIN 
// Compilato con Arduino21

#include <Servo.h> 
#include <IRremote.h> 

#define RECV_PIN 10   // pin per sensore IR
#define PING_PIN 11   // pin per sensore RADAR
#define       P1 12   // pin per pulsante

#define STNB_CODE1 0x81D    // Stop Philips TV remote
#define STNB_CODE2 0x1D     // Codice alternativo
#define WALK_CODE1 0x81C    // Play Philips TV remote
#define WALK_CODE2 0x1C     // Codice alternativo
#define SPEEDUP_CODE1 0x820 // Prg+ Philips TV remote
#define SPEEDUP_CODE2 0x20  // Codice alternativo
#define SPEEDDW_CODE1 0x821 // Prg- Philips TV remote
#define SPEEDDW_CODE2 0x21  // Codice alternativo
#define LEFT_CODE1    0x2C  // Left Philips remote
#define LEFT_CODE2    0x82C  // Codice alternativo
#define RIGHT_CODE1    0x2B  // Left Philips remote
#define RIGHT_CODE2    0x82B  // Codice alternativo

#define MODE_OFF       0    // Servi OFF
#define MODE_STANDBY   1    // Servi armati in posizione di riposo
#define MODE_INWALK    2    // Assume la posizione di partenza
#define MODE_WALK      3    // Cammina in avanti
#define MODE_INSTANDBY 4    // Assume la posizione di standby
#define MODE_LEFT      5    // Si gira verso sinistra
#define MODE_RIGHT     6    // Si gira a destra
#define MODE_REVWALK   7    // Cammina all'indietro

IRrecv irrecv(RECV_PIN);
decode_results results;

int RobotMode = MODE_OFF;   
int TimeOneStep = 6000;     // Tempo in msec per eseguire un passo completo

Servo servo0, servo1, servo2, servo3,
      servo4, servo5, servo6, servo7;  // oggetti servo

int leg_old[8] = {90, 90, 90, 90, 90, 90, 90, 90}; //posizione precedente dei servi
int leg[8];                 //posizione attuale dei servi
int i;

void setup() 
{ 
  Serial.begin(9600);       // Start seriale
  Serial.println("BIPE Aduino V1.0");
  irrecv.enableIRIn();      // Start ricevitore IR  
  irrecv.blink13(true);     // Lampeggio LED in ricezione IR attivo
  pinMode(P1, INPUT);       // Pulsante 
  digitalWrite(P1, HIGH);   // Abilita pull-up
  levelBat();               // Verifica stato batteria  
  Serial.println("Livello batteria OK.");  
  Serial.println("Inizializzo Servi...");  
  initServo();              // Inizializza servi
  Serial.println("Servi inizializzati.");
  inStandby();              // Robot in attesa di comando
} 

void loop() 
{ 
  if (irrecv.decode(&results)) IRcommand();
  if (RobotMode==MODE_WALK)   walk();
  if (RobotMode==MODE_REVWALK) walkReverse();
  if (RobotMode==MODE_LEFT)   leftWalk();  
  if (RobotMode==MODE_RIGHT)   rightWalk();
  levelBat();  
  if (RobotMode==MODE_STANDBY) delay(100); 
  if (digitalRead(P1)==0) P1Press();  

  int obstacle = readDistance();
  Serial.print("Ostacolo: ");
  Serial.println(obstacle, DEC);    
  if (obstacle<20)  inStandby();    

  // Ricezione seriale per setup servi
  if (Serial.available()) SerialSet();  
} 

void SerialSet()
{
   // E' arrivato un comando dalla seriale
  byte c;
  byte srv;

  while(Serial.available())     // finchè ci sono dati 
  {
      c = Serial.read();    // legge i dati e li salva in una variabile
      if ( 97 <= c <= 102)   Serial.print(c);
 }  
}

void IRcommand()
{
    // E' arrivato un comando via IR
    Serial.println(results.value, HEX);  // ECO su serial monitor per sapere il codice arrivato

    if (results.value == WALK_CODE1 || results.value == WALK_CODE2)   inWalk();     
    else if (results.value == LEFT_CODE1 || results.value == LEFT_CODE2)  inLeft();     
    else if (results.value == RIGHT_CODE1 || results.value == RIGHT_CODE2)  inRight();       
    else if (results.value == STNB_CODE1 || results.value == STNB_CODE2)  inStandby();            
    else if (results.value == SPEEDUP_CODE1 || results.value == SPEEDUP_CODE2) {
      if (TimeOneStep > 1000) TimeOneStep -= 500; }
    else if (results.value == SPEEDDW_CODE1 || results.value == SPEEDDW_CODE2) {
      if (TimeOneStep < 6000) TimeOneStep += 500; }
    Serial.print("TimeOneStep= ");      
    Serial.println(TimeOneStep);
    irrecv.resume(); // Resume decoding   
}  

void P1Press()
{
  // E' stato premuto il pulsante   
  while (digitalRead(P1)==0) delay(100);  
  if (RobotMode==MODE_WALK)  inStandby();            
  else if (RobotMode==MODE_STANDBY) inWalk(); 
}  

void levelBat()
{
  // controlla livello batteria  
  int VbatRAW = analogRead(A0);
  float Vbat = float(VbatRAW)/50;
  Serial.print("Vbat= ");
  Serial.println(Vbat, DEC);     
  if (Vbat<6.0)   {
    Serial.println("Livello batteria basso!");    
    inOff();    
  }  
}

void initServo()  
{
  // posizione iniziale dei servi
  servo0.attach(2);  // connette servo 
  delay(300);
  servo1.attach(3);  // connette servo 
  delay(300);  
  servo2.attach(4);  // connette servo 
  delay(300);
  servo3.attach(5);  // connette servo 
  delay(300);  
  servo4.attach(6);  // connette servo 
  delay(300);
  servo5.attach(7);  // connette servo 
  delay(300);  
  servo6.attach(8);  // connette servo 
  delay(300);
  servo7.attach(9);  // connette servo 
  delay(300);     
}

void inOff()
{
  // Spegne tutti i servi
  leg[0] = 90;
  leg[1] = 90;
  leg[2] = 90;
  leg[3] = 90;
  leg[4] = 90;
  leg[5] = 90;
  leg[6] = 90;
  leg[7] = 90;      
  setServo();  
  servo0.detach();  // connette servo 
  servo1.detach();  // connette servo 
  servo2.detach();  // connette servo 
  servo3.detach();  // connette servo 
  servo4.detach();  // connette servo 
  servo5.detach();  // connette servo 
  servo6.detach();  // connette servo 
  servo7.detach();  // connette servo 
  RobotMode = MODE_OFF;     
  // Da questo modalità si deve spegnere il robot e ricaricare le batterie
}  

void inStandby()
{
  // Posiziono tutti i servi al centro
  leg[0] = 90;
  leg[1] = 90;
  leg[2] = 90;
  leg[3] = 90;
  leg[4] = 90;
  leg[5] = 90;
  leg[6] = 90;
  leg[7] = 90;      
  setServo();  
  RobotMode = MODE_STANDBY;  
  Serial.println("Sono in Standby...");  
}  

void inWalk()
{
  // Si alza pronto per partire   
  leg[0] = 99;
  leg[1] = 126;
  leg[2] = 117;
  leg[3] = 54;
  leg[4] = 99;
  leg[5] = 126;
  leg[6] = 117;
  leg[7] = 54;      
  setServo();  
  RobotMode = MODE_WALK;
  Serial.println("Walk Mode...");   
}

void setServo() 
{  
   // Posiziona i servi alle cordinate specificate da leg[]  
   for (i=0; i<18; i++) {
       servo0.write(leg_old[0] + i*(leg[0]-leg_old[0])/18);  
       servo1.write(leg_old[1] + i*(leg[1]-leg_old[1])/18);        
       servo2.write(leg_old[2] + i*(leg[2]-leg_old[2])/18);  
       servo3.write(leg_old[3] + i*(leg[3]-leg_old[3])/18);      
       servo4.write(leg_old[4] + i*(leg[4]-leg_old[4])/18);  
       servo5.write(leg_old[5] + i*(leg[5]-leg_old[5])/18);        
       servo6.write(leg_old[6] + i*(leg[6]-leg_old[6])/18);  
       servo7.write(leg_old[7] + i*(leg[7]-leg_old[7])/18);    
       delay(TimeOneStep/4/18);
    }   
    leg_old[0]=leg[0];
    leg_old[1]=leg[1]; 
    leg_old[2]=leg[2];
    leg_old[3]=leg[3];  
    leg_old[4]=leg[4];
    leg_old[5]=leg[5]; 
    leg_old[6]=leg[6];
    leg_old[7]=leg[7];       
}  

void setServoWalk() 
{     
   // Posiziona i servi durante la camminata 
   for (i=1; i<=18; i++) {
       servo0.write(leg_old[0] + i*(leg[0]-leg_old[0])/18);          
       servo2.write(leg_old[2] + i*(leg[2]-leg_old[2])/18);       
       servo4.write(leg_old[4] + i*(leg[4]-leg_old[4])/18);       
       servo6.write(leg_old[6] + i*(leg[6]-leg_old[6])/18);  

      // servi delle zampe
         if ( i <= 9 ) 
           servo1.write(leg_old[1] + i*(leg[1]-leg_old[1])/9);         
         else  
           servo1.write(leg_old[1] + (18-i)*(leg[1]-leg_old[1])/9);      

         if ( i <= 9 ) 
           servo3.write(leg_old[3] + i*(leg[3]-leg_old[3])/9);                   
         else    
           servo3.write(leg_old[3] + (18-i)*(leg[3]-leg_old[3])/9); 

         if ( i <= 9 ) 
           servo5.write(leg_old[5] + i*(leg[5]-leg_old[5])/9);         
         else  
           servo5.write(leg_old[5] + (18-i)*(leg[5]-leg_old[5])/9);    

         if ( i <= 9 ) 
           servo7.write(leg_old[7] + i*(leg[7]-leg_old[7])/9);         
         else  
           servo7.write(leg_old[7] + (18-i)*(leg[7]-leg_old[7])/9);       

       delay(TimeOneStep/4/18);
    }   
    leg_old[0]=leg[0];
    leg_old[1]=126;//leg[1]; 
    leg_old[2]=leg[2];
    leg_old[3]=54;//leg[3];  
    leg_old[4]=leg[4];
    leg_old[5]=126;//leg[5]; 
    leg_old[6]=leg[6];
    leg_old[7]=54; //leg[7];  
    if (digitalRead(P1)==0) P1Press();  
    if (irrecv.decode(&results)) IRcommand();    
}  

void walk()
{
      // Coordinate per eseguire un passo

      //passo 1      
      leg[0] = 117;
      leg[1] = 126;
      leg[2] = 63;
      leg[3] = 90;   //posizione zampa alzata
      leg[4] = 81;
      leg[5] = 126;
      leg[6] = 99;
      leg[7] = 54;  
      setServoWalk();      
      if (RobotMode!=MODE_WALK) return;

      //passo 2      
      leg[0] = 63;
      leg[1] = 90;   // posizione zampa alzata
      leg[2] = 81;
      leg[3] = 54;
      leg[4] = 63;
      leg[5] = 126;
      leg[6] = 81;
      leg[7] = 54;  
      setServoWalk();
      if (RobotMode!=MODE_WALK) return;

      //passo 3      
      leg[0] = 81;
      leg[1] = 126;
      leg[2] = 99;
      leg[3] = 54;
      leg[4] = 117;
      leg[5] = 90;    // posizione zampa alzata
      leg[6] = 63;
      leg[7] = 54;  
      setServoWalk();
      if (RobotMode!=MODE_WALK) return; 

      //passo 4      
      leg[0] = 99;
      leg[1] = 126;
      leg[2] = 117;
      leg[3] = 54;
      leg[4] = 99;
      leg[5] = 126;
      leg[6] = 117;
      leg[7] = 90;    // posizione zampa alzata
      setServoWalk();       
}

void walkReverse()
{
      //passo 1      
      leg[0] = 63;
      leg[1] = 126;
      leg[2] = 117;
      leg[3] = 90;  // si alza
      leg[4] = 99;
      leg[5] = 126;
      leg[6] = 81;
      leg[7] = 54;  
      setServoWalk();      
      if (RobotMode!=MODE_WALK) return;   

      //passo 2      
      leg[0] = 117;
      leg[1] = 126;
      leg[2] = 99;
      leg[3] = 54;
      leg[4] = 117;
      leg[5] = 90;  // si alza
      leg[6] = 99;
      leg[7] = 54;  
      setServoWalk();
      if (RobotMode!=MODE_WALK) return;

      //passo 3      
      leg[0] = 99;
      leg[1] = 126;
      leg[2] = 81;
      leg[3] = 54;
      leg[4] = 63;
      leg[5] = 126;
      leg[6] = 117;
      leg[7] = 90;  // si alza  
      setServoWalk();
      if (RobotMode!=MODE_WALK) return; 

      //passo 4      
      leg[0] = 81;
      leg[1] = 90; // si alza
      leg[2] = 63;
      leg[3] = 54;
      leg[4] = 81;
      leg[5] = 126;
      leg[6] = 63;
      leg[7] = 54;  
      setServoWalk();       
}

void inLeft()
{
  // Si alza pronto per girare a sinistra   
  leg[0] = 63;
  leg[1] = 126;
  leg[2] = 81;
  leg[3] = 54;
  leg[4] = 99;
  leg[5] = 126;
  leg[6] = 117;
  leg[7] = 54;      
  setServo();  
  RobotMode = MODE_LEFT;
  Serial.println("Left Mode...");   
}

void leftWalk()
{
      //passo 1      
      leg[0] = 81;
      leg[1] = 126;
      leg[2] = 99;
      leg[3] = 54;  
      leg[4] = 117;
      leg[5] = 126;
      leg[6] = 63;
      leg[7] = 90;//*  
      setServoWalk();      
      if (RobotMode!=MODE_LEFT) return;   

      //passo 2      
      leg[0] = 99;
      leg[1] = 126;
      leg[2] = 117;
      leg[3] = 54;
      leg[4] = 63;
      leg[5] = 90;//*
      leg[6] = 99;
      leg[7] = 54;  
      setServoWalk();
      if (RobotMode!=MODE_LEFT) return;

      //passo 3      
      leg[0] = 117;
      leg[1] = 126;
      leg[2] = 63;
      leg[3] = 90;//*
      leg[4] = 81;
      leg[5] = 126;
      leg[6] = 99;
      leg[7] = 54;   
      setServoWalk();
      if (RobotMode!=MODE_LEFT) return; 

      //passo 4      
      leg[0] = 63;
      leg[1] = 90;//*
      leg[2] = 81;
      leg[3] = 54;
      leg[4] = 99;
      leg[5] = 126;
      leg[6] = 117;
      leg[7] = 54;  
      setServoWalk();         
}

void inRight()
{
  // Si alza pronto per girare a destra   
  leg[0] = 99;
  leg[1] = 126;
  leg[2] = 117;
  leg[3] = 54;
  leg[4] = 63;
  leg[5] = 126;
  leg[6] = 81;
  leg[7] = 54;      
  setServo();  
  RobotMode = MODE_RIGHT;
  Serial.println("Right Mode...");   
}

void rightWalk()
{
      //passo 1      
      leg[0] = 81;
      leg[1] = 126;
      leg[2] = 99;
      leg[3] = 54;  
      leg[4] = 117;
      leg[5] = 90;//*
      leg[6] = 63;
      leg[7] = 54;  
      setServoWalk();      
      if (RobotMode!=MODE_RIGHT) return;   

      //passo 2      
      leg[0] = 63;
      leg[1] = 126;
      leg[2] = 81;
      leg[3] = 54;
      leg[4] = 99;
      leg[5] = 126;
      leg[6] = 117;
      leg[7] = 90;//*  
      setServoWalk();
      if (RobotMode!=MODE_RIGHT) return;

      //passo 3      
      leg[0] = 117;
      leg[1] = 90;//*
      leg[2] = 63;
      leg[3] = 54;
      leg[4] = 81;
      leg[5] = 126;
      leg[6] = 99;
      leg[7] = 54;   
      setServoWalk();
      if (RobotMode!=MODE_RIGHT) return; 

      //passo 4      
      leg[0] = 99;
      leg[1] = 126;
      leg[2] = 117;
      leg[3] = 90;//*
      leg[4] = 63;
      leg[5] = 126;
      leg[6] = 81;
      leg[7] = 54;  
      setServoWalk();           
} 

long readDistance()
{
  // Procedura per leggere la presenza di ostacoli
  // Viene generato un PING di 2usec ed atteso l'ECO di risposta
  long duration, cm;
  pinMode(PING_PIN, OUTPUT);
  digitalWrite(PING_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(PING_PIN, HIGH);
  delayMicroseconds(5);
  digitalWrite(PING_PIN, LOW);

  // Lo stesso pin che genera il trigger è usato per la lettura
  // del segnale di ritorno
  pinMode(PING_PIN, INPUT);
  duration = pulseIn(PING_PIN, HIGH);

  // ritorna distanza ostacolo in cm
  return duration / 29 / 2;
}

Make sure that the servos are aligned and that the legs are neither too open nor too closed, taking as reference the pictures posted here .

 

 

Connect the servos to the robot Spider

Servo Arduino Pin Connector shield Function
Servo 0 2 S1 Angle right foreleg
Servo 1 3 S2 Elevation of right foreleg
Servo 2 4 S3 Angle of the right hind leg
Servo 3 5 S4 Elevation of the right hind leg
Servo 4 6 S5 Angle left hind leg
Servo 5 7 S6 Elevation of the left hind paw
Servo 6 8 S7 Angle left foreleg
Servo 7 9 S8 Elevation of left foreleg

 

Turning on after 1 second (after the warm-up switching power supply) all the servos will be placed in the neutral point. It may happen that some servos vibrate slightly, this is due to the internal mechanism that has yet to find the center point, sometimes just a small blow to the servant to fix things.

For this robot we never anticipated that you can edit parameters, movements are many and complex and there are too many variables to set, we preferred to find a setup that could offer the best performance in every situation. For our prototype LiPo battery that powers it has been established under the structure, right through to the servos, ensuring, in addition to the centering of weight, a low center of gravity.

Let us see now the analysis of the firmware describing those functions that are common to all the robots such as the procedure that reads the distance from obstacles by means of the sensor SRF05:

 

Code 6

long readDistance()
{
  long duration, cm;
  pinMode(PING_PIN, OUTPUT);
  digitalWrite(PING_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(PING_PIN, HIGH);
  delayMicroseconds(5);
  digitalWrite(PING_PIN, LOW);
  pinMode(PING_PIN, INPUT);
  duration = pulseIn(PING_PIN, HIGH);
  // ritorna distanza ostacolo in cm
  return duration / 29 / 2;
}

The procedure foresees to send a pulse duration of 2usec to the sensor, which, proceeds generating a series of ultrasound to the outside. The same pin is subsequently used as input for reading, via the function PulseIn, the time taken by the sound to reach the obstacle, bounce and return to the sensor, the period during which the sensor maintains a high level of the line. The time taken by the ultrasound to go and return to the sensor is proportional to the distance of the object.

 

Here also the procedure for reading the voltage on the battery:

 

Code 7

void levelBat()
{
  int VbatRAW = analogRead(A0);
  float Vbat = float(VbatRAW)/50;
  Serial.print("Vbat= ");
  Serial.println(Vbat, DEC);    
  if (Vbat<6.0)   {
    Serial.println("Livello batteria basso!");   
    inOff();   
  } 
}

 

The procedure is simple, plan to read the analog channel A0 of Arduino and save the result into a variable VbatRAW. As explained above, by dividing this value by 50, is obtained by the voltage in volts of the battery. Since excessively discharge the battery can damage it, we expected an alarm to the level below which the robot is immediately stopped and all the servos are disabled.  The threshold value is defined in 6.0 V ideal for use with a battery pack consisting of two cell LiPo or six if you use NiMh or NiCd cells, eight cells used instead if you can increase this value up to 8.0 volts or, one volt per used cell.

 

Another common procedure is called to all the robots initServo () to initialize the servos:

 

Code 8

void initServo() 
{
  // posizione iniziale dei servi
  servo0.attach(2);  // connette servo
  delay(300);
........
  servo7.attach(9);  // connette servo
  delay(300);    
}

 

The function Servo.attach() associates each object provides the respective servo output, from this moment the servant reaches the PWM signal.

 

The procedure inOff () performs the opposite function by removing the pin from their association with the servos and leaving them with no control.

 

Code 9

void inOff()
{
  leg[0] = 90;
.....
  leg[7] = 90;     
  setServo(); 
  servo0.detach();  // connette servo
....
  servo7.detach();  // connette servo
  RobotMode = MODE_OFF;    
}

 

The function to put in sleep mode the robot is called Standby() and simply place all the servos in the central position. In the case of the robot Filippo and BIPE the servos are positioned in their respective neutral points whose values are contained in the vector named leg_ntr [].

 

Code 10

void inStandby()
{
  leg[0] = 90;
....
  leg[7] = 90;     
  setServo(); 
  RobotMode = MODE_STANDBY; 
  Serial.println("Sono in Standby..."); 
}

 

A very important procedure is to ensure that the servos have to place to desired coordinates:

 

Code 11

void setServo()
{ 
   for (i=0; i<18; i++) {
       servo0.write(leg_old[0] + i*(leg[0]-leg_old[0])/18); 
       servo1.write(leg_old[1] + i*(leg[1]-leg_old[1])/18);       
       servo2.write(leg_old[2] + i*(leg[2]-leg_old[2])/18); 
       servo3.write(leg_old[3] + i*(leg[3]-leg_old[3])/18);     
       servo4.write(leg_old[4] + i*(leg[4]-leg_old[4])/18); 
       servo5.write(leg_old[5] + i*(leg[5]-leg_old[5])/18);       
       servo6.write(leg_old[6] + i*(leg[6]-leg_old[6])/18); 
       servo7.write(leg_old[7] + i*(leg[7]-leg_old[7])/18);   
       delay(TimeOneStep/4/18);
    }  
    leg_old[0]=leg[0];
    leg_old[1]=leg[1];
    leg_old[2]=leg[2];
    leg_old[3]=leg[3]; 
    leg_old[4]=leg[4];
    leg_old[5]=leg[5];
    leg_old[6]=leg[6];
    leg_old[7]=leg[7];      
}

 

If we set directly the servo, it was a sudden movement and the robot would move in spurts. He prefers, instead, gradually controlling the servo to bring it to the desired position in a defined time. To do this you must define a vector leg[] that contains the coordinates to be achieved by each servo and a vector leg_old[] that contains the actual coordinates. The procedure controls the servos by sending them all coordinated by the intermediate value at the target value in a time defined by the variable TimeOneStep. This system allows us to obtain fluid movements.

Only the robot spider there is a procedure called setServoWalk() because it is necessary that some servos are moving at different speeds than the other. During the walk the three legs in contact with the floor moving slowly, the fourth foot must lift and move fast in the opposite direction to progress.

 

 

Download

 Gerber for Shield
   Gerber for Filippo
   Gerber for Bipe
   Gerber for Spider


 

-->-->-->-->-->-->
-->-->

ARDUINO WIFI RGB LAMP [IKEA DUDERÖ MODDING]

 

We create an application based on Arduino, that allows you to control brightness and color of a RGB strip LED via local network or Internet through a WiFi or Ethernet shield

How it works

The system that we propose is based on the Arduino UNO, on which are mounted two shield: the Ethernet or WIFI Shield, which provides the connection to LAN, and the RGB shield which mounts three power drivers to control the LED strip.
In Arduino must be loaded different sketch depending of the type of connection you choose (Ethernet or WiFi). The sketch allows you to manage communication via LAN and create a web interface (which will come to those who try to access via a local network) and run the commands received.
Arduino is like a web server, an HTML page is showed through a browser, by introducing into the address bar the IP address corresponding to the ethernet/WIFI shield.

This means that the lamp can be turned on and controlled by any device on the network or remotely via the Internet. The web page shows the current setting of R, G, B of the lamp and allows you to edit them.

 

The shield RGB

Arduino controls the LED channels by a shield very simple, containing three MOSFET enhancement-mode n-channel type P36NF06; each MOSFET is driven on the gate, through a resistor, with the logic signal that Arduino sends. To be precise, pin 3 controls T3 (red), pin 5 controls T2 (green) and pin 6 controls T1 (blue), each line has a status LED, polarized by a limiting resistor (LEDs indicate how it is behaving this channel). Note that Arduino controls the individual transistors by PWM signals, which duty cycle determines the presence and intensity of a certain color; more precisely, the width of the pulses can changes from a minimum to a maximum to decide how much light should be the group of LEDs of the respective color.

The drain of each MOSFET controls the load which must be connected with the anode to the positive line of the common power supply (+); for each channel there is a connector with a positive contact (goes on line common) and a negative (corresponding to the respective drain MOSFET).
We have provided the possibility to power the LEDs in two ways: with the power drawn by Arduino contact Vin (in which case you should close the jumper on Vin) or with a voltage supplied to the terminal PWR (PWR jumper closed on), you can opt for the first solution if you think your lamps absorbs less than 1.5 amps, but if you need more power you have give power apart from the shield, with a suitable power supply.
Note that by closing the jumper on Vin, the Arduino must be supplied at 12 V with a power supply capable of delivering all the current required.

 

R1: 1 kohm
R2: 390 ohm
R3: 180 ohm
R4: 330 ohm
R5: 330 ohm
R6: 330 ohm

T1: STP36NE06
T2: STP36NE06
T3: STP36NE06

LD1: Led 5 mm blue
LD2: Led 5 mm green
LD3: Led 5 mm red

D1: 6A600

- Screw a 2

R1: 1 kohm
R2: 390 ohm
R3: 180 ohm
R4: 330 ohm
R5: 330 ohm
R6: 330 ohm

T1: STP36NE06
T2: STP36NE06
T3: STP36NE06

LD1: Led 5 mm blu (510LB7C)
LD2: Led 5 mm verde
LD3: Led 5 mm rosso

D1: 6A600

Varie:
- Screw 2 via(4 pz.)
- Strip M/F 6 via (2 pz.)
- Strip M/F 8 via (2 pz.)

The sketch

/* IKEA Dudero mods WIFI Version

 created 2011
 by Boris Landoni

 This example code is in the public domain.

http://www.open-electronics.org

http://www.futurashop.it

http://blog.elettronicain.it/

 */

// Inclusione Libreria per Server Web WiFi
#include <WiServer.h>
#include <avr/pgmspace.h>
#include <EEPROM.h>

int red = 3;    // RED LED connected to PWM pin 3
int green = 5;    // GREEN LED connected to PWM pin 5
int blue = 6;    // BLUE LED connected to PWM pin 6
int r=50; int g=100; int b=150;
int rup; int gup; int bup;
int fader=0;
int inc=10;
String inString = String(50);
char buffer[160]; // make sure this is large enough for the largest string it must hold

// Definizione Parametri Rete Wireless
#define WIRELESS_MODE_INFRA	1  // Infrastrutturata (basata su Access Point)
#define WIRELESS_MODE_ADHOC	2  // Ad-hoc (senza Access Point)

unsigned char local_ip[] = {192, 168, 0, 89};      // Indirizzo IP
unsigned char gateway_ip[] = {192, 168, 0, 254};	    // Indirizzo gateway IP
unsigned char subnet_mask[] = {255, 255, 255, 0};   // Subnet Mask
const prog_char ssid[] PROGMEM = {"AP_FES"};	    // SSID access point

// Selezione tipo di cifratura rete Wireless
unsigned char security_type = 3;  // 0 -> nessuna cifratura
                                  // 1 -> cifratura WEP
                                  // 2 -> cifratura WPA
                                  // 3 -> cifratura WPA2

// Password cifratura per WPA/WPA2 (max. 64 cratteri)
const prog_char security_passphrase[] PROGMEM = {"12345678"};

// Password cifratura per WEP 128-bit keys
prog_uchar wep_keys[] PROGMEM = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
				 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
				 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
				 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

// Selezione tipo di rete Wireless infrastrutturata
unsigned char wireless_mode = WIRELESS_MODE_INFRA;

// Variabili per lunghezza SSID e password di cifratura
unsigned char ssid_len;
unsigned char security_passphrase_len;

prog_char string_0[] PROGMEM  = "<html><head><title>Boris's Project</title></head><script language=\"javascript\"> var alphaStr = \"0123456789ABCDEF\";";
prog_char string_1[] PROGMEM  = "var alphaArr = [\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\",\"A\",\"B\",\"C\",\"D\",\"E\",\"F\"]; var RGB = [";
prog_char string_2[] PROGMEM  = "];function pulsRED(){document.bgColor='#FF0000';RGB = [255,0,0]}function pulsGRE(){document.bgColor='#00FF00';RGB = [0,255,0]}";
prog_char string_3[] PROGMEM  = "function pulsBLU(){document.bgColor='#0000FF';RGB = [0,0,255]}function pulsYEL(){document.bgColor='#FFFF00';RGB = [255,255,0]}";
prog_char string_4[] PROGMEM  = "function pulsPIN(){document.bgColor='#FF00FF';RGB = [255,0,255]}function pulsCEL(){document.bgColor='#00FFFF';RGB = [0,255,255]}";
prog_char string_5[] PROGMEM  = "function pulsWHI(){document.bgColor='#FFFFFF';RGB = [255,255,255]}";
prog_char string_6[] PROGMEM  = " ";
prog_char string_7[] PROGMEM  = "function HEX_from_RGB(){document.bgColor = '#' + DEC_to_HEX(RGB[0]) + DEC_to_HEX(RGB[1]) + DEC_to_HEX(RGB[2]);}";
prog_char string_8[] PROGMEM  = "function adjRED(incr){	RGB[0] += incr;	if (RGB[0] > 255) RGB[0] = 255;	if (RGB[0] < 0) RGB[0] = 0;}";
prog_char string_9[] PROGMEM  = "function adjGRN(incr)	{RGB[1] += incr;if (RGB[1] > 255) RGB[1] = 255;	if (RGB[1] < 0) RGB[1] = 0;}";
prog_char string_10[] PROGMEM  = "function adjBLU(incr)	{RGB[2] += incr;if (RGB[2] > 255) RGB[2] = 255;	if (RGB[2] < 0) RGB[2] = 0;}";
prog_char string_11[] PROGMEM = "function setRED(r) { RGB[0] = r; } function setGRN(g) { RGB[1] = g; } function setBLU(b) { RGB[2] = b; }";
prog_char string_12[] PROGMEM = "function newRGB() { HEX_from_RGB(); } </script> <script language=\"javascript\"> var i_a; ";
prog_char string_13[] PROGMEM = "function DEC_to_HEX(dec) {var n_ = Math.floor(dec / 16); var _n = dec - n_ * 16; return alphaArr[n_] + alphaArr[_n];	}";
prog_char string_14[] PROGMEM = "function HEX_to_DEC(hex){var n_ = alphaStr.indexOf(hex.substring(0,1)); var _n = alphaStr.indexOf(hex.substring(1,2)); return n_ * 16 + _n;	}";
prog_char string_15[] PROGMEM = "function updateFields(){var d = document.colForm;d.r.value = RGB[0];	d.g.value = RGB[1];	d.b.value = RGB[2];	}";
prog_char string_16[] PROGMEM = "function setRGB(){var d = document.colForm; var R = d.r.value;	var G = d.g.value;	var B = d.b.value;";
prog_char string_17[] PROGMEM = "setRED(parseInt(R));	setGRN(parseInt(G));	setBLU(parseInt(B));	newRGB(); updateFields();} </script>";
prog_char string_18[] PROGMEM = "</head><body><center><form method=GET, name=\"colForm\"><h1>The INTERNET RGB LAMP</h1> <table> <tr> <td valign=\"top\"> <input type=\"text\" name=\"r\"> ";
prog_char string_19[] PROGMEM = "<input type=\"text\" name=\"g\"> <input type=\"text\" name=\"b\"> <input type=\"button\" value=\"Calculate\" onclick=\"setRGB();\">";
prog_char string_20[] PROGMEM = " </td></tr> <tr><td><CENTER><input type=\"button\" class=\"tweak\" value=\"Red+\" onclick=\"adjRED(i_a);newRGB();updateFields();\">";
prog_char string_21[] PROGMEM = "<input type=\"button\" class=\"tweak\" value=\"Green+\" onclick=\"adjGRN(i_a);newRGB();updateFields();\"><input type=\"button\" class=\"tweak\" value=\"Blue+\"";
prog_char string_22[] PROGMEM = "onclick=\"adjBLU(i_a);newRGB();updateFields();\"> <select name=\"inc\" onchange=\"i_a = parseInt(document.colForm.inc.options";
prog_char string_23[] PROGMEM = "[document.colForm.inc.selectedIndex].value);\"> <option value=\"1\"";//selected
prog_char string_24[] PROGMEM = ">inc/speed = 1x <option value=\"5\"";
prog_char string_25[] PROGMEM = ">inc/speed = 5x <option value=\"10\"";
prog_char string_26[] PROGMEM = ">inc/speed = 10x <option value=\"25\"";
prog_char string_27[] PROGMEM = ">inc/speed = 25x <option value=\"50\"";
prog_char string_28[] PROGMEM = ">inc/speed = 50x <option value=\"100\"";
prog_char string_29[] PROGMEM = ">inc/speed = 100x <option value=\"150\"";
prog_char string_30[] PROGMEM = ">inc/speed = 150x <option value=\"200\"";
prog_char string_31[] PROGMEM = ">inc/speed = 200x <option value=\"250\"";
prog_char string_32[] PROGMEM = ">inc/speed = 250x</select><input type=";
prog_char string_33[] PROGMEM = "\"button\" class=\"tweak\" value=\"Red-\" onclick=\"adjRED(0-i_a);newRGB();updateFields();\"><input type=\"button\" class=\"tweak\" value=\"Green-\"";
prog_char string_34[] PROGMEM = "onclick=\"adjGRN(0-i_a);newRGB();updateFields();\"><input type=\"button\" class=\"tweak\" value=\"Blue-\" onclick=\"adjBLU(0-i_a);newRGB();updateFields();\">";
prog_char string_35[] PROGMEM = "</CENTER></td> <tr><td><CENTER>Fader<input type=\"radio\" name=\"fad\" value=\"1\"";
prog_char string_36[] PROGMEM = "/> On<input type=\"radio\" name=\"fad\" value=\"0\" ";
prog_char string_37[] PROGMEM = "/> Off</CENTER></td></tr> </tr></td> </tr> <input type=\"submit\" style=\" width:80;height:44px;background-color:FF0000;\" onclick=\"pulsRED();updateFields();\";>";
prog_char string_38[] PROGMEM = "<input type=\"submit\" style=\" width:80;height:44px;background-color:00FF00;\" onclick=\"pulsGRE();updateFields();\";>";
prog_char string_39[] PROGMEM = "<input type=\"submit\" style=\" width:80;height:44px;background-color:0000FF;\" onclick=\"pulsBLU();updateFields();\";>";
prog_char string_40[] PROGMEM = "<input type=\"submit\" style=\" width:80;height:44px;background-color:FFFF00;\" onclick=\"pulsYEL();updateFields();\";>";
prog_char string_41[] PROGMEM = "<input type=\"submit\" style=\" width:80;height:44px;background-color:FF00FF;\" onclick=\"pulsPIN();updateFields();\";>";
prog_char string_42[] PROGMEM = "<input type=\"submit\" style=\" width:80;height:44px;background-color:00FFFF;\" onclick=\"pulsCEL();updateFields();\";>";
prog_char string_43[] PROGMEM = "<input type=\"submit\" style=\" width:80;height:44px;background-color:FFFFFF;\" onclick=\"pulsWHI();updateFields();\";>";
prog_char string_44[] PROGMEM = "<tr><td><CENTER><input type=\"submit\" value=\"Set colors\"></CENTER></td></tr>   ";
prog_char string_45[] PROGMEM = "</table> </form> <script language=\"javascript\">newRGB(); updateFields(); ";
prog_char string_46[] PROGMEM = "i_a = parseInt(document.colForm.inc.options[document.colForm.inc.selectedIndex].value);</script>";
prog_char string_47[] PROGMEM = "<font size= 2>Powered by Open-Electronics.org - Boris Landoni</font>"; //please don't remove  ";
prog_char string_48[] PROGMEM  = "<br></center></body></html>";
prog_char string_49[] PROGMEM  = "";
prog_char string_50[] PROGMEM  = "";
prog_char string_51[] PROGMEM  = "";

PROGMEM const char *string_table[] = // change "string_table" name to suit
{
string_0,
string_1,
string_2,
string_3,
string_4,
string_5,
string_6,
string_7,
string_8,
string_9,
string_10,
string_11,
string_12,
string_13,
string_14,
string_15,
string_16,
string_17,
string_18,
string_19,
string_20,
string_21,
string_22,
string_23,
string_24,
string_25,
string_26,
string_27,
string_28,
string_29,
string_30,
string_31,
string_32,
string_33,
string_34,
string_35,
string_36,
string_37,
string_38,
string_39,
string_40,
string_41,
string_42,
string_43,
string_44,
string_45,
string_46,
string_47,
string_48,
string_49,
string_50,
string_51
};

void setup()
{
  // start the Ethernet connection and the server:
// Inizializzo WiServer (Gestione_Richieste_Web per creare/trasmettere pagine HTML)
      WiServer.init (Gestione_Richieste_Web);
      // Inizializzo porta seriale
      Serial.begin (9600);
      WiServer.enableVerboseMode (false);

      Serial.println("Serial READY");
      Serial.println("WiFi READY");
      Serial.println("Server READY");

      r = EEPROM.read(1);
      g = EEPROM.read(2);
      b = EEPROM.read(3);
      inc = EEPROM.read(4);
      fader = EEPROM.read(5);
} 

void loop()  { 

    // Avvio WiServer
  WiServer.server_task();

  delay(10);

  if (fader==1){
    funcfader();
  }

}

// Gestione diverse richieste provenienti dal WEB
// INPUT:   URL pagina web richiesta
// OUTPUT:  Flag URL riconosciuto/non riconosciutoo
boolean Gestione_Richieste_Web (char* URL) {
  Serial.print("Richiesta Web - URL->");
  Serial.println(URL); 

  // Se URL richiesto corrisponde a "/" (pagina index)
  if (strcmp (URL, "/") == 0) {
    // Secondo gli I/O creo e invio le pagine Web
    Serial.println("pagina index");
    printWebPage();

    // Ritorno URL è stato riconosciuto
    return true;
  }    // Chiusura if URL richieso corrisponde a "/" (pagina index)

  // Se URL richieso corrisponde a "?OPERATION=ACCENDI_ROSSO
  if (strncmp (URL, "/?r=*",4) == 0) {

    Serial.println("pagina operazione"); 

                char colorArr[5];
                String temp="";
                inString=URL;
                Serial.print("inString: ");
                Serial.println(inString);

                int Pos_r = inString.indexOf("r");
                int Pos_g = inString.indexOf("g");
                int Pos_b = inString.indexOf("b");
                int Pos_i = inString.indexOf("inc");
                int Pos_f = inString.indexOf("fad");
                int End = inString.indexOf("HTTP");
                Serial.print("Pos_r: ");
                Serial.println(Pos_r);
                Serial.print("Pos_g: ");
                Serial.println(Pos_g);
                Serial.print("Pos_b: ");
                Serial.println(Pos_b);
                Serial.print("Pos_i: ");
                Serial.println(Pos_i);
                Serial.print("Pos_f: ");
                Serial.println(Pos_f);
                Serial.print("End: ");
                Serial.println(End);
                if(Pos_r>=0){
                   temp=inString.substring((Pos_r+2), (Pos_g-1));
                   temp.toCharArray(colorArr, 5);
                   r=(atoi(colorArr));
                   Serial.print("red: ");
                   Serial.println(r);
                   EEPROM.write(1, r);
                }
                if(Pos_g>=0){
                   temp=inString.substring((Pos_g+2), (Pos_b-1));
                   temp.toCharArray(colorArr, 5);
                   g=(atoi(colorArr));
                   Serial.print("green: ");
                   Serial.println(g);
                   EEPROM.write(2, g);
                }         

                if(Pos_b>=0){
                   temp=inString.substring((Pos_b+2), (Pos_i-1));
                   temp.toCharArray(colorArr, 5);
                   b=(atoi(colorArr));
                   Serial.print("blue: ");
                   Serial.println(b);
                   EEPROM.write(3, b);
                }      

                if(Pos_i>=0){
                   temp=inString.substring((Pos_i+4), (Pos_f-1));
                   temp.toCharArray(colorArr, 5);
                   inc=(atoi(colorArr));
                   Serial.print("inc: ");
                   Serial.println(inc);
                   EEPROM.write(4, inc);
                } 

                if(Pos_f>=0){
                   temp=inString.substring((Pos_f+4), (End-1));
                   temp.toCharArray(colorArr, 5);
                   fader=(atoi(colorArr));
                   Serial.print("fader: ");
                   Serial.println(fader);
                   EEPROM.write(5, fader);
                }     

               if ((Pos_r>=0)&&(Pos_g>=0)&&(Pos_b>=0)) {
                 rgb(r,g,b);
               }

    // Secondo gli I/O creo e invio le pagine Web
    printWebPage();

    // Ritorno URL è stato riconosciuto
    return true;
  }    // Chiusura if URL richieso corrisponde a "?OPERATION=ACCENDI_ROSSO"

  // Ritorno URL non riconosciuto
  return false;
}

 void printWebPage2()
{
      int tmp=0;
      Serial.println("printWebPage");
      // send a standard http response header

//      WiServer.print("HTTP/1.1 200 OK");
//      WiServer.print("Content-Type: text/html");
//      WiServer.print();

      //strcpy_P(buffer, (char*)pgm_read_word(&(string_table[0]))); // Necessary casts and dereferencing, just copy.
      //WiServer.print( buffer );
      //Serial.println( buffer );
      for (int i = 0; i < 51; i++)
      {
          //strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); // Necessary casts and dereferencing, just copy.
          //WiServer.print( buffer );
          WiServer.print_P((char*)pgm_read_word(&(string_table[i])));
          //Serial.println( buffer );
          //delay(500);
      }

}          

void printWebPage()
{
      int tmp=0;
      Serial.println("printWebPage");
      // send a standard http response header
      //WiServer.print_P("HTTP/1.1 200 OK");
      //WiServer.print_P("Content-Type: text/html");

      //strcpy_P(buffer, (char*)pgm_read_word(&(string_table[0]))); // Necessary casts and dereferencing, just copy.
      WiServer.print_P((char*)pgm_read_word(&(string_table[0])));
      //Serial.println( buffer );
      for (int i = 1; i < 51; i++)
      {
          /*if (i==9)
          {
              strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i])));  //butto tutto nell'array buffer
              for (tmp=0 ; tmp < sizeof(buffer); tmp++)
              {
                if (buffer[tmp]=='#')
                {
                  //Serial.println( "trovato ##### " ); 

                }

              }
          }
          else
          {
            strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); // Necessary casts and dereferencing, just copy.
          }*/
          //strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); // Necessary casts and dereferencing, just copy.
          WiServer.print_P((char*)pgm_read_word(&(string_table[i])));
          //Serial.println( buffer );
          if (i==1)
          {
            char tmpstr[4];
            WiServer.print( itoa(r,tmpstr,10) );
            //Serial.println( itoa(r,tmpstr,10) );
            WiServer.print( "," );
            //Serial.println("," );
            WiServer.print( itoa(g,tmpstr,10) );
            //Serial.println( itoa(g,tmpstr,10) );
            WiServer.print( "," );
            //Serial.println( "," );
            WiServer.print( itoa(b,tmpstr,10) );
            //Serial.println( itoa(b,tmpstr,10) );
          }

          if (i==23){if (inc==1){WiServer.print("selected");}}
          if (i==24){if (inc==5){WiServer.print("selected");}}
          if (i==25){if (inc==10){WiServer.print("selected");}}
          if (i==26){if (inc==25){WiServer.print("selected");}}
          if (i==27){if (inc==50){WiServer.print("selected");}}
          if (i==28){if (inc==100){WiServer.print("selected");}}
          if (i==29){if (inc==150){WiServer.print("selected");}}
          if (i==30){if (inc==200){WiServer.print("selected");}}
          if (i==31){if (inc==250){WiServer.print("selected");}}

          if (i==35)
          {
            if (fader==1){
              WiServer.print("checked");
            }
          }
          if (i==36)
          {
            if (fader==0){
              WiServer.print("checked");
            }
          }
      }
     Serial.println("FINE printWebPage"); 

}

void funcfader(){
    Serial.println("fader");
    if (rup==1){r+=1;}
    else{r-=1;}
    if (r>=255){rup=0;}
    if (r<=0){rup=1;}

    if (gup==1){g+=1;}
    else{g-=1;}
    if (g>=255){gup=0;}
    if (g<=0){gup=1;}

    if (bup==1){b+=1;}
    else{b-=1;}
    if (b>=255){bup=0;}
    if (b<=0){bup=1;}

    delay(inc*2);
    rgb(r, g, b);
}

void rgb(int r, int g, int b)
{

  Serial.print("RGB: ");
  Serial.print(r);
  Serial.print(" ");
  Serial.print(g);
  Serial.print(" ");
  Serial.print(b);
  if (r>255) r=255;
  if (g>255) g=255;
  if (b>255) b=255;
  if (r<0) r=0;
  if (g<0) g=0;
  if (b<0) b=0;

  analogWrite(red, r);
  analogWrite(green, g);
  analogWrite(blue, b);
}

 

/* IKEA Dudero mods Ethernet Version

 created 2011
 by Boris Landoni

 This example code is in the public domain.

http://www.open-electronics.org

http://www.futurashop.it

http://blog.elettronicain.it/

 */

#include <SPI.h>
#include <Ethernet.h>
#include <avr/pgmspace.h>
#include <EEPROM.h>

int red = 3;    // RED LED connected to PWM pin 3
int green = 5;    // GREEN LED connected to PWM pin 5
int blue = 6;    // BLUE LED connected to PWM pin 6
int r=50; int g=100; int b=150;
int rup; int gup; int bup;
int fader=0;
int inc=10;
String inString = String(50);
char buffer[160]; // make sure this is large enough for the largest string it must hold

byte mac[] = {  0x90, 0xA2, 0xDA, 0x00, 0x1D, 0x89 };
byte ip[] = { 192,168,0,88 };
byte gateway[] = { 192, 168, 0, 1 };
byte subnet[] = { 255, 255, 255, 0 };

/*

*/

prog_char string_0[] PROGMEM  = "<html><head><title>Boris's Project</title></head><script language=\"javascript\"> var alphaStr = \"0123456789ABCDEF\";";
prog_char string_1[] PROGMEM  = "var alphaArr = [\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\",\"A\",\"B\",\"C\",\"D\",\"E\",\"F\"]; var RGB = [";
prog_char string_2[] PROGMEM  = "];function pulsRED(){document.bgColor='#FF0000';RGB = [255,0,0]}function pulsGRE(){document.bgColor='#00FF00';RGB = [0,255,0]}";
prog_char string_3[] PROGMEM  = "function pulsBLU(){document.bgColor='#0000FF';RGB = [0,0,255]}function pulsYEL(){document.bgColor='#FFFF00';RGB = [255,255,0]}";
prog_char string_4[] PROGMEM  = "function pulsPIN(){document.bgColor='#FF00FF';RGB = [255,0,255]}function pulsCEL(){document.bgColor='#00FFFF';RGB = [0,255,255]}";
prog_char string_5[] PROGMEM  = "function pulsWHI(){document.bgColor='#FFFFFF';RGB = [255,255,255]}";
prog_char string_6[] PROGMEM  = "";
prog_char string_7[] PROGMEM  = "function HEX_from_RGB(){document.bgColor = '#' + DEC_to_HEX(RGB[0]) + DEC_to_HEX(RGB[1]) + DEC_to_HEX(RGB[2]);}";
prog_char string_8[] PROGMEM  = "function adjRED(incr){	RGB[0] += incr;	if (RGB[0] > 255) RGB[0] = 255;	if (RGB[0] < 0) RGB[0] = 0;}";
prog_char string_9[] PROGMEM  = "function adjGRN(incr)	{RGB[1] += incr;if (RGB[1] > 255) RGB[1] = 255;	if (RGB[1] < 0) RGB[1] = 0;}";
prog_char string_10[] PROGMEM  = "function adjBLU(incr)	{RGB[2] += incr;if (RGB[2] > 255) RGB[2] = 255;	if (RGB[2] < 0) RGB[2] = 0;}";
prog_char string_11[] PROGMEM = "function setRED(r) { RGB[0] = r; } function setGRN(g) { RGB[1] = g; } function setBLU(b) { RGB[2] = b; }";
prog_char string_12[] PROGMEM = "function newRGB() { HEX_from_RGB(); } </script> <script language=\"javascript\"> var i_a; ";
prog_char string_13[] PROGMEM = "function DEC_to_HEX(dec) {var n_ = Math.floor(dec / 16); var _n = dec - n_ * 16; return alphaArr[n_] + alphaArr[_n];	}";
prog_char string_14[] PROGMEM = "function HEX_to_DEC(hex){var n_ = alphaStr.indexOf(hex.substring(0,1)); var _n = alphaStr.indexOf(hex.substring(1,2)); return n_ * 16 + _n;	}";
prog_char string_15[] PROGMEM = "function updateFields(){var d = document.colForm;d.r.value = RGB[0];	d.g.value = RGB[1];	d.b.value = RGB[2];	}";
prog_char string_16[] PROGMEM = "function setRGB(){var d = document.colForm; var R = d.r.value;	var G = d.g.value;	var B = d.b.value;";
prog_char string_17[] PROGMEM = "setRED(parseInt(R));	setGRN(parseInt(G));	setBLU(parseInt(B));	newRGB(); updateFields();} </script>";
prog_char string_18[] PROGMEM = "</head><body><center><form method=GET, name=\"colForm\"><h1>The INTERNET RGB LAMP</h1> <table> <tr> <td valign=\"top\"> <input type=\"text\" name=\"r\"> ";
prog_char string_19[] PROGMEM = "<input type=\"text\" name=\"g\"> <input type=\"text\" name=\"b\"> <input type=\"button\" value=\"Calculate\" onclick=\"setRGB();\">";
prog_char string_20[] PROGMEM = " </td></tr> <tr><td><CENTER><input type=\"button\" class=\"tweak\" value=\"Red+\" onclick=\"adjRED(i_a);newRGB();updateFields();\">";
prog_char string_21[] PROGMEM = "<input type=\"button\" class=\"tweak\" value=\"Green+\" onclick=\"adjGRN(i_a);newRGB();updateFields();\"><input type=\"button\" class=\"tweak\" value=\"Blue+\"";
prog_char string_22[] PROGMEM = "onclick=\"adjBLU(i_a);newRGB();updateFields();\"> <select name=\"inc\" onchange=\"i_a = parseInt(document.colForm.inc.options";
prog_char string_23[] PROGMEM = "[document.colForm.inc.selectedIndex].value);\"> <option value=\"1\"";//selected
prog_char string_24[] PROGMEM = ">inc/speed = 1x <option value=\"5\"";
prog_char string_25[] PROGMEM = ">inc/speed = 5x <option value=\"10\"";
prog_char string_26[] PROGMEM = ">inc/speed = 10x <option value=\"25\"";
prog_char string_27[] PROGMEM = ">inc/speed = 25x <option value=\"50\"";
prog_char string_28[] PROGMEM = ">inc/speed = 50x <option value=\"100\"";
prog_char string_29[] PROGMEM = ">inc/speed = 100x <option value=\"150\"";
prog_char string_30[] PROGMEM = ">inc/speed = 150x <option value=\"200\"";
prog_char string_31[] PROGMEM = ">inc/speed = 200x <option value=\"250\"";
prog_char string_32[] PROGMEM = ">inc/speed = 250x</select><input type=";
prog_char string_33[] PROGMEM = "\"button\" class=\"tweak\" value=\"Red-\" onclick=\"adjRED(0-i_a);newRGB();updateFields();\"><input type=\"button\" class=\"tweak\" value=\"Green-\"";
prog_char string_34[] PROGMEM = "onclick=\"adjGRN(0-i_a);newRGB();updateFields();\"><input type=\"button\" class=\"tweak\" value=\"Blue-\" onclick=\"adjBLU(0-i_a);newRGB();updateFields();\">";
prog_char string_35[] PROGMEM = "</CENTER></td> <tr><td><CENTER>Fader<input type=\"radio\" name=\"fad\" value=\"1\"";
prog_char string_36[] PROGMEM = "/> On<input type=\"radio\" name=\"fad\" value=\"0\" ";
prog_char string_37[] PROGMEM = "/> Off</CENTER></td></tr> </tr></td> </tr> <input type=\"submit\" style=\" width:80;height:44px;background-color:FF0000;\" onclick=\"pulsRED();updateFields();\";>";
prog_char string_38[] PROGMEM = "<input type=\"submit\" style=\" width:80;height:44px;background-color:00FF00;\" onclick=\"pulsGRE();updateFields();\";>";
prog_char string_39[] PROGMEM = "<input type=\"submit\" style=\" width:80;height:44px;background-color:0000FF;\" onclick=\"pulsBLU();updateFields();\";>";
prog_char string_40[] PROGMEM = "<input type=\"submit\" style=\" width:80;height:44px;background-color:FFFF00;\" onclick=\"pulsYEL();updateFields();\";>";
prog_char string_41[] PROGMEM = "<input type=\"submit\" style=\" width:80;height:44px;background-color:FF00FF;\" onclick=\"pulsPIN();updateFields();\";>";
prog_char string_42[] PROGMEM = "<input type=\"submit\" style=\" width:80;height:44px;background-color:00FFFF;\" onclick=\"pulsCEL();updateFields();\";>";
prog_char string_43[] PROGMEM = "<input type=\"submit\" style=\" width:80;height:44px;background-color:FFFFFF;\" onclick=\"pulsWHI();updateFields();\";>";
prog_char string_44[] PROGMEM = "<tr><td><CENTER><input type=\"submit\" value=\"Set colors\"></CENTER></td></tr>   ";
prog_char string_45[] PROGMEM = "</table> </form> <script language=\"javascript\">newRGB(); updateFields(); ";
prog_char string_46[] PROGMEM = "i_a = parseInt(document.colForm.inc.options[document.colForm.inc.selectedIndex].value);</script>";
prog_char string_47[] PROGMEM = "<font size= 2>Powered by Open-Electronics.org - Boris Landoni</font>"; //please don't remove  ";
prog_char string_48[] PROGMEM  = "<br></center></body></html>";
prog_char string_49[] PROGMEM  = "";
prog_char string_50[] PROGMEM  = "";
prog_char string_51[] PROGMEM  = "";

PROGMEM const char *string_table[] = // change "string_table" name to suit
{
string_0,
string_1,
string_2,
string_3,
string_4,
string_5,
string_6,
string_7,
string_8,
string_9,
string_10,
string_11,
string_12,
string_13,
string_14,
string_15,
string_16,
string_17,
string_18,
string_19,
string_20,
string_21,
string_22,
string_23,
string_24,
string_25,
string_26,
string_27,
string_28,
string_29,
string_30,
string_31,
string_32,
string_33,
string_34,
string_35,
string_36,
string_37,
string_38,
string_39,
string_40,
string_41,
string_42,
string_43,
string_44,
string_45,
string_46,
string_47,
string_48,
string_49,
string_50,
string_51
};

// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
Server server(80);

void setup()
{
  // start the Ethernet connection and the server:
      Serial.begin(9600);
      Ethernet.begin(mac, ip,gateway,subnet);
      server.begin();
      Serial.println("Serial READY");
      Serial.println("Ethernet READY");
      Serial.println("Server READY");
      r = EEPROM.read(1);
      g = EEPROM.read(2);
      b = EEPROM.read(3);
      inc = EEPROM.read(4);
      fader = EEPROM.read(5);
} 

void loop()  {
//  // fade in from min to max in increments of 5 points:
//  for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) {
//    // sets the value (range from 0 to 255):
//    //analogWrite(red, fadeValue);
//    // wait for 30 milliseconds to see the dimming effect
//    rgb(fadeValue,fadeValue,fadeValue);
//    delay(30);
//  }
//
//  // fade out from max to min in increments of 5 points:
//  for(int fadeValue = 255 ; fadeValue >= 0; fadeValue -=5) {
//    // sets the value (range from 0 to 255):
//    //analogWrite(red, fadeValue);
//    // wait for 30 milliseconds to see the dimming effect
//    rgb(fadeValue,fadeValue,fadeValue);
//    delay(30);
//  } 

  if (fader==1){
    funcfader();
  }

      Client client = server.available();

      if (client) {
        Serial.println("client");
        // an http request ends with a blank line
        boolean current_line_is_blank = true;
        while (client.connected()) {

          if (client.available()) {

            char c = client.read();
            if (inString.length() < 50) {
            inString.concat(c);

            } 

            if (c == '\n' && current_line_is_blank) {
                char colorArr[5];
                String temp="";
                Serial.print("inString: ");
                Serial.println(inString);

                int Pos_r = inString.indexOf("r");
                int Pos_g = inString.indexOf("g");
                int Pos_b = inString.indexOf("b");
                int Pos_i = inString.indexOf("inc");
                int Pos_f = inString.indexOf("fad");
                int End = inString.indexOf("HTTP");
                Serial.print("Pos_r: ");
                Serial.println(Pos_r);
                Serial.print("Pos_g: ");
                Serial.println(Pos_g);
                Serial.print("Pos_b: ");
                Serial.println(Pos_b);
                Serial.print("Pos_i: ");
                Serial.println(Pos_i);
                Serial.print("Pos_f: ");
                Serial.println(Pos_f);
                Serial.print("End: ");
                Serial.println(End);

                if(Pos_r>=0){
                   temp=inString.substring((Pos_r+2), (Pos_g-1));
                   temp.toCharArray(colorArr, 5);
                   r=(atoi(colorArr));
                   Serial.print("red: ");
                   Serial.println(r);
                   EEPROM.write(1, r);
                }
                if(Pos_g>=0){
                   temp=inString.substring((Pos_g+2), (Pos_b-1));
                   temp.toCharArray(colorArr, 5);
                   g=(atoi(colorArr));
                   Serial.print("green: ");
                   Serial.println(g);
                   EEPROM.write(2, g);
                }         

                if(Pos_b>=0){
                   temp=inString.substring((Pos_b+2), (Pos_i-1));
                   temp.toCharArray(colorArr, 5);
                   b=(atoi(colorArr));
                   Serial.print("blue: ");
                   Serial.println(b);
                   EEPROM.write(3, b);
                }      

                if(Pos_i>=0){
                   temp=inString.substring((Pos_i+4), (Pos_f-1));
                   temp.toCharArray(colorArr, 5);
                   inc=(atoi(colorArr));
                   Serial.print("inc: ");
                   Serial.println(inc);
                   EEPROM.write(4, inc);
                } 

                if(Pos_f>=0){
                   temp=inString.substring((Pos_f+4), (End-1));
                   temp.toCharArray(colorArr, 5);
                   fader=(atoi(colorArr));
                   Serial.print("fader: ");
                   Serial.println(fader);
                   EEPROM.write(5, fader);
                }     

               if ((Pos_r>=0)&&(Pos_g>=0)&&(Pos_b>=0)) {
                 rgb(r,g,b);
               }
            printWebPage( &client);
            break;
            }
            if (c == '\n') {
            // we're starting a new line
            current_line_is_blank = true;
            } else if (c != '\r') {
            // we've gotten a character on the current line
            current_line_is_blank = false;
            }
          }
        }
        // give the web browser time to receive the data
        delay(1);

        inString = "";
        client.stop();
      }

}

void printWebPage(Client *client)
{
      int tmp=0;
      Serial.println("printWebPage");
      // send a standard http response header
      client->println("HTTP/1.1 200 OK");
      client->println("Content-Type: text/html");
      client->println();

      strcpy_P(buffer, (char*)pgm_read_word(&(string_table[0]))); // Necessary casts and dereferencing, just copy.
      client->println( buffer );
      //Serial.println( buffer );
      for (int i = 1; i < 51; i++)
      {
          /*if (i==9)
          {
              strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i])));  //butto tutto nell'array buffer
              for (tmp=0 ; tmp < sizeof(buffer); tmp++)
              {
                if (buffer[tmp]=='#')
                {
                  //Serial.println( "trovato ##### " ); 

                }

              }
          }
          else
          {
            strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); // Necessary casts and dereferencing, just copy.
          }*/
          strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); // Necessary casts and dereferencing, just copy.
          client->println( buffer );
          if (i==1)
          {
            client->print( r );client->print( "," );client->print( g );client->print( "," );client->print( b );
          }

          if (i==23){if (inc==1){client->print("selected");}}
          if (i==24){if (inc==5){client->print("selected");}}
          if (i==25){if (inc==10){client->print("selected");}}
          if (i==26){if (inc==25){client->print("selected");}}
          if (i==27){if (inc==50){client->print("selected");}}
          if (i==28){if (inc==100){client->print("selected");}}
          if (i==29){if (inc==150){client->print("selected");}}
          if (i==30){if (inc==200){client->print("selected");}}
          if (i==31){if (inc==250){client->print("selected");}}

          if (i==35)
          {
            if (fader==1){
              client->print("checked");
            }
          }
          if (i==36)
          {
            if (fader==0){
              client->print("checked");
            }
          }
//          switch(i){
//
//              case 1:
//                  //itoa (tempC, buffer, 10); client->print( buffer ); Serial.print( buffer ); client->print( "," ); Serial.print( "," ); itoa ((int(tempC * 100) % 100), buffer, 10); client->print( buffer ); Serial.print( buffer ); break;
//              case 2:
//                  //if(digitalRead(rele)) st4=41;
//                  //else st4=42;
//                  //strcpy_P(buffer, (char*)pgm_read_word(&(string_table[st4]))); client->println( buffer ); Serial.println( buffer ); break;
//              case 3:
//                  //strcpy_P(buffer, (char*)pgm_read_word(&(string_table[st6]))); client->println( buffer ); Serial.println( buffer ); break;
//              case 4:
//              case 5:
//              case 6:
//          }
          delay(30);
      }

}

void funcfader(){
    Serial.println("fader");
    if (rup==1){r+=1;}
    else{r-=1;}
    if (r>=255){rup=0;}
    if (r<=0){rup=1;}

    if (gup==1){g+=1;}
    else{g-=1;}
    if (g>=255){gup=0;}
    if (g<=0){gup=1;}

    if (bup==1){b+=1;}
    else{b-=1;}
    if (b>=255){bup=0;}
    if (b<=0){bup=1;}

    delay(inc*2);
    rgb(r, g, b);
}

void rgb(int r, int g, int b)
{

  Serial.print("RGB: ");
  Serial.print(r);
  Serial.print(" ");
  Serial.print(g);
  Serial.print(" ");
  Serial.print(b);
  if (r>255) r=255;
  if (g>255) g=255;
  if (b>255) b=255;
  if (r<0) r=0;
  if (g<0) g=0;
  if (b<0) b=0;

  analogWrite(red, r);
  analogWrite(green, g);
  analogWrite(blue, b);
}

 

 

 

The web page

We conclude seeing the commands and reports available on the web page, there are buttons to issue commands, the option radio to select mode and some boxes where you write parameters. We start from the top, where we find the seven buttons, each relating to a color: each of them set in the lamp the combination of the LEDs R, G and B to obtain the corresponding color; receiving the command Arduino sets its color. Below these buttons are three boxes, with the Calculate button to the right: from left to right, they represent the colors red, green and blue. In each box, you can write, with a number between 0 and 255, the intensity that we have employed the same light, for example, typing 255 in the middle box we illuminate at full intensity green light.
The value in each cell can be varied with the buttons below Red+ Green+ and Blue+ (which increases the light intensity, respectively, red, green and blue) or by Red- Green- and Blue- buttons that reduce the intensity. Clicking on the Calculate button, see what color will obtain, whereas with Set colors send a request for setting the color intensity corresponding to the combination of the three boxes.
The last section of the web page is that of the fader: it is the effect of color change continues, activated by clicking in the option box next to On the same name (Fader) to disable this function you must click Off. By activating the fader, we will see the light of the lamp shades change cyclically from the currently set color, you can also choose between multiple execution speed of the cycle, the drop down menu which is accessed by clicking the middle box inc/speed was above a Fader section.

To build the project

Open Electronics 20 Feb 14:15

Lighted plexiglass Christmas ornaments (Arduino version)

In the previous post we showed you how to make small Christmas shapes using an RGB LED and a small circuit based on PIC.
The designs were obtained working with the CNC some acrylic sheets.
But our CNC can do much more … Therefore we decided to make the greatest figure and design a new driver that mounts more LEDs.

Just because we do not like things simple we recreated all using a system based on Arduino.
This allows you to create an open source system easy to modify.
The microcontroller is an Atmega328 preprogrammed with the bootloader of Arduino UNO. The programming can be done via a USB / TTL (eg FTDI5V of SparkFun).
The circuit operation is very similar to that of the smallest model: here we find the photocell that allows to verify the amount of light present in the environment, but in this case, you can adjust the sensitivity of the circuit by a trimmer.

BOM

R1: 10 kohm
R2: 820 ohm
R3: 820 ohm
R4: 1 kohm
R5: 820 ohm
R6: 820 ohm
R7: 1 kohm
R8: 820 ohm
R9: 820 ohm
R10: 1 kohm
R11: 820 ohm
R12: 820 ohm
R13: 1 kohm
R14: 820 ohm
R15: 820 ohm
R16: 1 kohm
R17: 820 ohm
R18: 820 ohm
R19: 1 kohm
R20: 820 ohm
R21: 820 ohm
R22: 1 kohm
R23: 820 ohm
R24: 820 ohm
R25: 1 kohm
R26: 820 ohm
R27: 820 ohm
R28: 1 kohm
R29: 10 kohm
R30: 4,7 kohm
R31: 10 kohm
R32: 4,7 kohm
R33: 4,7 kohm
R34: 10 kohm
R35: 4,7 kohm
R36: 10 kohm
R37: 4,7 kohm
R38: 10 kohm
R39: Trimmer 4,7 kohm MV

C1: 100 nF
C2: 470 µF 25 VL
C3: 470 µF 25 VL
C4: 100 nF
C5: 15 pF
C6: 15 pF
C7: 100 nF
C8: 100 µF 25 VL

T1: BC547
T2: BC547
T3: BC547

LD1: LED 5 mm RGB c.a.
LD2: LED 5 mm RGB c.a.
LD3: LED 5 mm RGB c.a.
LD4: LED 5 mm RGB c.a.
LD5: LED 5 mm RGB c.a.
LD6: LED 5 mm RGB c.a.
LD7: LED 5 mm RGB c.a.
LD8: LED 5 mm RGB c.a.
LD9: LED 5 mm RGB c.a.

U1: 7805
U2: ATMEGA328P-PU (with bootloader)

Q1: 16 MHz

LDR1: photoresistor 2÷20 kohm

- Terminal 2 via (3 pz.)
- Socket 14+14
- Battery 12V/2A
- Strip male 6 via
- Plug
- Switch

Comparing the value read from the A/D converter connected to the photoresistor with that connected to trimmer R39, the micro decides whether to start the sequence of fading, or whether turn off the LEDs. RGB LEDs are driven by the transistor; this choice permit to control with a single line of microcontroller, more LEDs in order to create large luminous figures.

As you can see, we use a line dell’ATmega for each of the primary colors of red, green and blue, so it is clear that all the diodes will do the same play of light. Of course isn’t required to mount all the LEDs provided in the circuit: you mount those who need to obtain a good visual effect on the size of the pattern in the Plexiglass. Note that there are three terminals on the PCB: one to connect the power switch (ON / OFF) a second (BATT) to apply to the circuit power supply and a third (CHARGE) for a possible battery charger lead or a small 12-volt solar panel, which already incorporates the charging circuit. These solutions allow you to use the figures lack the power grid. In this regard, an analog input of the microcontroller is dedicated to control the battery voltage: when it drops below 10 V, the circuit will emit flashes to warn that the energy is about to end.

This circuit is evidently intended to be used externally (provided it is properly isolated) and will turn on and off independently, thanks to the ambient light sensor, which will illuminate the figures in the evening to let off in the morning. In short, is a solution to decorate the garden or backyard.

Building shapes
The materials chosen for this application are clear polycarbonate (or methacrylate) or Plexiglas, which can give the shape you want. Then we need to affect, deep enough (half or two thirds the thickness of the plate) the drawing or writing that you want to appear bright.

The Sketch

//****************************************************************
//*  Name    : RGB controller for common anode led               *
//*  Author  : Landoni Boris                                     *
//*  www.open-electronics.org                                    *
//*  blog.elettronicain.it                                       *
//*  www.futurashop.it                                           *
//****************************************************************

int red = 9;    // RED LED connected to PWM pin 3
int green = 10;    // GREEN LED connected to PWM pin 5
int blue = 11;    // BLUE LED connected to PWM pin 6
int photo = A4;    // BLUE LED connected to PWM pin 6
int trim = A5;    // BLUE LED connected to PWM pin 6
int volt = A2;    // BLUE LED connected to PWM pin 6
int r=50; int g=100; int b=150;
int rup; int gup; int bup;
int fader=1;
int inc=10;
void setup()
{
      Serial.begin(9600);
      Serial.println("Serial READY");
      rgb(r, g, b);
      r = random(0,255);
      g = random(0,255);
      b = random(0,255);

} 

void loop()  {

  Serial.print("trim  ");
  Serial.println(analogRead(trim)*2);  

  Serial.print("photo ");
  Serial.println(analogRead(photo)); 

  Serial.print("volt ");
  Serial.println(analogRead(volt));
  if (analogRead(volt)<600){
      Serial.println("low battery");
      rgb(0, 0, 0);
      delay(500);
      rgb(255, 255, 255);
  }

  if ((analogRead(trim)*2)>analogRead(photo)){
      Serial.println("trim > photo  -  off");
      rgb(0, 0, 0);
      fader=0;
  }
  else
  {
    if (fader==0){
      r = random(0,255);
      g = random(0,255);
      b = random(0,255);
    }
    fader=1;

  }
  //delay(2000);

  if (fader==1){
    funcfader();
  }
}

void funcfader(){
    Serial.println("fader");
    if (rup==1){r+=1;}
    else{r-=1;}
    if (r>=255){rup=0;}
    if (r<=0){rup=1;}

    if (gup==1){g+=1;}
    else{g-=1;}
    if (g>=255){gup=0;}
    if (g<=0){gup=1;}

    if (bup==1){b+=1;}
    else{b-=1;}
    if (b>=255){bup=0;}
    if (b<=0){bup=1;}

    delay(inc*2);
    rgb(r, g, b);
}

void rgb(int r, int g, int b)
{
  Serial.print("RGB: ");
  Serial.print(r);
  Serial.print(" ");
  Serial.print(g);
  Serial.print(" ");
  Serial.println(b);
  if (r>255) r=255;
  if (g>255) g=255;
  if (b>255) b=255;
  if (r<0) r=0;
  if (g<0) g=0;
  if (b<0) b=0;
  analogWrite(red, r);
  analogWrite(green, g);
  analogWrite(blue, b);
}

 

Star
Reindeer
Santa Claus
Tree

IKEA lamp mod – STRÅLA

I love IKEA and her low cost products.

Last week I found this STRÅLA lamp.

The cost is $4.99, so I bought it.
Lighting the lamp I saw that it ‘s very pretty but also … too soft…

So I thought to modify the LED and add a RGB led.
With simple modify you can obtain a dinamic lamp.
I used an Arduino to do a fast work, but of course it isn’t necessary.
You can use a small microcontroller like a PIC12F675, or a ATTiny.

And this it the result:

How to

Before all, you have to buy a STRÅLA 

Open the package

And disassemble the original LED

As you can see the LED shape isn’t normal, but there is a cone in the center to better spread the light.
So I modify the RGB led to obtain the same effects and I also smoothed the surface.

Connect the wire to the led and reassemble all.

To connect the RGB led I used a strip wire and some pin.

And now you can connect this pin to PWM ports of Arduino.

The black, blue and white wire are the RGB pin of the LED.

The red one is the Anode.

 The sketch

/* IKEA Strala mods

 created 2011
 by Boris Landoni

 This example code is in the public domain.

http://www.open-electronics.org

http://www.futurashop.it

http://blog.elettronicain.it/

 */

#include <EEPROM.h>

int red = 9;    // RED LED connected to PWM pin 3
int green = 10;    // GREEN LED connected to PWM pin 5
int blue = 11;    // BLUE LED connected to PWM pin 6
int r=50; int g=100; int b=150;
int rup; int gup; int bup;
int fader=1;
int inc=10;
void setup()
{
  // start the Ethernet connection and the server:
      Serial.begin(9600);
      Serial.println("Serial READY");
      r = EEPROM.read(1);
      g = EEPROM.read(2);
      b = EEPROM.read(3);
      inc = EEPROM.read(4);
      fader = EEPROM.read(5);
      rgb(r, g, b);
} 

void loop()  { 

  if (fader==1){
    funcfader();
  }

}

void funcfader(){
    Serial.println("fader");
    if (rup==1){r+=1;}
    else{r-=1;}
    if (r>=255){rup=0;}
    if (r<=0){rup=1;}

    if (gup==1){g+=1;}
    else{g-=1;}
    if (g>=255){gup=0;}
    if (g<=0){gup=1;}

    if (bup==1){b+=1;}
    else{b-=1;}
    if (b>=255){bup=0;}
    if (b<=0){bup=1;}

    delay(inc*2);
    rgb(r, g, b);
}

void rgb(int r, int g, int b)
{

  Serial.print("RGB: ");
  Serial.print(r);
  Serial.print(" ");
  Serial.print(g);
  Serial.print(" ");
  Serial.print(b);
  if (r>255) r=255;
  if (g>255) g=255;
  if (b>255) b=255;
  if (r<0) r=0;
  if (g<0) g=0;
  if (b<0) b=0;

  analogWrite(red, r);
  analogWrite(green, g);
  analogWrite(blue, b);
}

Good modding

Open Electronics 09 Nov 17:27
arduino  featured  gadget  ikea  mods