top of page
Nombre de visites :
1260
Ressources ARDUINO
Écran OLED 128x64
Écran OLED 128x64

Test d’un écran OLED

128×64 I²C

test_ecran_oled_i2c_128x64_001_lowres.jp
test_ecran_oled_i2c_128x64_002_lowres.jp

/*

PROGRAMME BASIQUE POUR TESTER L’ÉCRAN OLED 128×64 I²C

RÉFÉRENCE AliExpress DE L’ÉCRAN

http://fr.aliexpress.com/item/1Pcs-Yellow-blue-double-color-128X64-OLED-LCD-LED-Display-Module-For-Arduino-0-96/32305641669.html

 

VERSION ORIGINALE DU PROGRAMME

http://www.projetsdiy.fr/ssd1306-mini-ecran-oled-i2c-128x64-arduino/

 

LIBRAIRIE Adafruit_SSD1306

https://github.com/adafruit/Adafruit_SSD1306.git

 

CONNEXIONS

GND GND

VDD +5V

SCK pin A5

SDA pin A4

 

MICROCONTRÔLEUR

Clone Arduino Nano

 

REMARQUES

Il faut éditer le fichier Adafruit_SSD1306.h de la manière suivante :

- À la ligne 69, décommenter le code `#define SSD1306_128_64`

- À la ligne 70, commenter le code `#define SSD1306_128_32`

 

Cet écran est séparé en deux zones verticales

- Une zone de 16 px de haut avec des pixels jaunes

- Une zone de 48 px de haut avec des pixels bleus Les deux zones sont séparées d’une largeur d’environ 1 pixel qui apparaît donc toujours noire.

 

La communication I²C fonctionne sans les résistances de pull-up. Cela dit, il est sans doute préférable d’ajouter deux résistances de 4.7 kΩ entre SCK et VDD ainsi qu’entre SDA et VDD.

 

mai 2016, ouilogique.com

 

*/

 

#include <Wire.h>

#include <Adafruit_SSD1306.h>

 

#define OLED_RESET 4

Adafruit_SSD1306 display( OLED_RESET );

 

#if( SSD1306_LCDHEIGHT != 64 )

#error( "Height incorrect, please fix Adafruit_SSD1306.h!" );

#endif

 

void setup()

{

// Initialise la communication I²C à l’adresse 0x3C.

display.begin( SSD1306_SWITCHCAPVCC, 0x3C );

display.clearDisplay();

 

// Affiche des textes

afficheTextes();

}

 

void loop() { }

 

void afficheTextes( void )

{

display.setTextSize( 2 );

display.setTextColor( WHITE );

display.clearDisplay();

 

display.setCursor( 4, 0 );

display.println( "ouilogique" );

 

display.setCursor( 4, 16 );

display.println( "ouilogique" );

 

display.setTextSize( 1 ); d

 

isplay.setCursor( 35, 32 );

display.println( "ouilogique" );

 

display.setCursor( 35, 40 );

display.println( "ouilogique" );

 

display.setCursor( 35, 48 );

display.println( "ouilogique" );

 

cadreEcran();

display.display();

}

 

void cadreEcran( void )

{

display.drawRect( 0, 0, display.width()-2, display.height()-2, WHITE );

}

Librairie Adafruit :

https://github.com/adafruit/Adafruit_SSD1306.git

Fichier « Zip »

Finding IR remote code
ARDUINO finding IR REMOTE CODE
 
 
Finding the IR Codes of Any IR Remote Using Arduino
We make several projects on various platforms and we always need the codes of any appliance, console, etc just by using an Arduino.
 
Things used in this project
  • Arduino UNO & Genuino UNO
  • IR receiver (generic)
  • IR Remote
 
Anyone or the one which you want to use in your project.
Story
Introduction
Most of the appliances from TV, DTH receiver , DVD Players to AC, etc are controlled wirelessly using IR remotes.
If you want to make an IR based project with a remote which you bought from the market or the remote of your AC, TV ,etc. then, you should be aware of the codes which are sent by the remote to the IR receiver in the appliance or device.
 
Working on Basics
IR remote has a button and a microcontroller with IR LED attached. When a button is pressed, a microcontroller identified the button and sends the corresponding modulated signals (codes) to the IR LED. Then, the IR LED sends it to the IR receiver in the appliance.
We can't see the infrared(IR) light because their wavelength is not in our spectrum.
IR-signal-1.png
IR-signal-2.png
 
 
System in the appliance demodulate the signals(codes) and the checks the function corresponding to it and executes it. Each function has a different code.
Every IR operated appliance has different codes for different function.
Hookup
Follow the steps:
  • Connect the first pin from left (OUT pin) with the pin 11 of Arduino.
  • Hook the middle pin (GND pin) with the GND pin of the Arduino.
  • Connect the third pin (VCC pin) with the 5 V pin of the Arduino.
 
Uploading and Testing
Remember to install the IRremote.h library from here.
  • Copy or download the code attached with the project.
  • Hit upload and open serial monitor.
  • Take any remote you want to use or you want the codes off it and press any button.
  • Now, see in the serial monitor. You will see a code of the corresponding button you pressed.
  • Note the codes on a paper or copy them in a document file on PC.
 
You can also run the online simulator for further
 
 
Schematics
IR-UNO.png
 
 
Code

/*

* https://github.com/chauhannaman98

*

* sketch.ino

*

* July 25, 2018 © GPL3+ * Author : Naman Chauhan

*/

 

#include <IRremote.h> //including infrared remote header file

 

int RECV_PIN = 11; // the pin where you connect the output pin of IR sensor IRrecv irrecv(RECV_PIN);

decode_results results;

 

void setup()

{

Serial.begin(9600);

irrecv.enableIRIn();

}

 

void loop()

{

if (irrecv.decode(&results))

{

int value = results.value;

Serial.println(" ");

Serial.print("Code: ");

Serial.println(results.value); //prints the value a a button press Serial.println(" ");

irrecv.resume(); // Receive the next value

Serial.println("*****************");

}

}

IR receiver
ARDUINO IR RECEIVER
 
 
Sketch

/*    -------------------------------------------------
      +===============================================+
      |  ARDUINO IR-REMOTE HOME AUTOMATION MK1v1      |
      |               (OPENSOURCE)                    |
      |mail me: applemindinventions@gmail.com         |
      +===============================================+
      -------------------------------------------------

*/
#include <IRremote.h>

int RECV_PIN = 12;    //tsop1738 output pin connected to D8
#define buzzer 10  //buzzer conected pin 12

int a = 1;
int b = 1;
int c = 1;
int d = 1;


IRrecv irrecv(RECV_PIN);

decode_results results;

void setup()
{

  pinMode(buzzer, OUTPUT);
  digitalWrite(buzzer, LOW);
  digitalWrite(buzzer, LOW);
  digitalWrite(6, LOW);
  digitalWrite(5, LOW);
  digitalWrite(4, LOW);
  digitalWrite(3, LOW);
  Serial.begin(9600);

  irrecv.enableIRIn();
}

void loop()
{
  if (irrecv.decode(&results))
  {
    Serial.println(results.value, HEX);

    {
      if (results.value == 0x1FE48B7) // paste your hex code

      {
        a++;
        int x = a % 2;
        digitalWrite(7, x);
        digitalWrite(buzzer, HIGH);
        delay(200);
        digitalWrite(buzzer, LOW);
      }
      else if (results.value == 0x1FE50AF) //paste your hex code
      {

        b++;
        int x = b % 2;
        digitalWrite(6, x);
        digitalWrite(buzzer, HIGH);
        delay(200);
        digitalWrite(buzzer, LOW);
      }
      else if (results.value == 0x1FED827) //paste your hex code
      {
        c++;
        int x = c % 2;
        digitalWrite(5, x);
        digitalWrite(buzzer, HIGH);
        delay(200);
        digitalWrite(buzzer, LOW);
      }
      else if (results.value == 0x1FEF807) ///paste your hex code
      {
        b++;
        int x = d % 2;
        digitalWrite(4, x);
        digitalWrite(buzzer, HIGH);
        delay(200);
        digitalWrite(buzzer, HIGH);
      }


      irrecv.resume(); //resume,continue recieving ir-signals
    }
  }
}
 

IR remote
ARDUINO using IR REMOTE
 
 
OVERVIEW
Using an IR Remote is a great way to have wireless control of your Arduino project.
Infrared remotes are simple and easy to use.  In this tutorial we will be connecting the IR receiver to the UNO, and then use a Library that was designed for this particular sensor.
In our sketch we will have all the IR Hexadecimal codes that are available on this remote, we will also detect if the code was recognized and also if we are holding down a key.
CONNECTIONS
IRremote-Schematics-1024x584.png
 
 
There are 3 connections to the IR Receiver.
The connections are : Signal, Voltage and Ground.
The “-” is the Ground, “S” is signal, and middle pin is Voltage 5V.
THE CODE
First download the Library (link below) and extract it to your “Library” folder inside your IDE software, it should be named “IRremote”
Next we will move the “RobotIRremote” out of the Library folder, we do this because that library conflicts with the one we will be using.  You can just drag it back inside the library folder once you are done programming your microcontroller.
Once you have installed the Library, just go ahead and restart your IDE Software.
You can watch our Tutorial video to get more information.

#include "IRremote.h"

 

int receiver = 11; // Signal Pin of IR receiver to Arduino Digital Pin 11

 

/*-----( Declare objects )-----*/

IRrecv irrecv(receiver); // create instance of 'irrecv'

decode_results results; // create instance of 'decode_results'

 

void setup() /*----( SETUP: RUNS ONCE )----*/

{

Serial.begin(9600);

Serial.println("IR Receiver Button Decode");

irrecv.enableIRIn(); // Start the receiver

}/*--(end setup )---*/

 

void loop() /*----( LOOP: RUNS CONSTANTLY )----*/

{

if (irrecv.decode(&results)) // have we received an IR signal?

{

translateIR();

irrecv.resume(); // receive the next value

}

}/* --(end main loop )-- */

 

/*-----( Function )-----*/

 

void translateIR() // takes action based on IR code received

// describing Remote IR codes

 

{

switch(results.value)

{

case 0xFF629D: Serial.println(" FORWARD"); break;

case 0xFF22DD: Serial.println(" LEFT"); break;

case 0xFF02FD: Serial.println(" -OK-"); break;

case 0xFFC23D: Serial.println(" RIGHT"); break;

case 0xFFA857: Serial.println(" REVERSE"); break;

case 0xFF6897: Serial.println(" 1"); break;

case 0xFF9867: Serial.println(" 2"); break;

case 0xFFB04F: Serial.println(" 3"); break;

case 0xFF30CF: Serial.println(" 4"); break;

case 0xFF18E7: Serial.println(" 5"); break;

case 0xFF7A85: Serial.println(" 6"); break;

case 0xFF10EF: Serial.println(" 7"); break;

case 0xFF38C7: Serial.println(" 8"); break;

case 0xFF5AA5: Serial.println(" 9"); break;

case 0xFF42BD: Serial.println(" *"); break;

case 0xFF4AB5: Serial.println(" 0"); break;

case 0xFF52AD: Serial.println(" #"); break;

case 0xFFFFFFFF: Serial.println(" REPEAT");break;

 

default: Serial.println(" other button ");

}// End Case

 

delay(500); // Do not get immediate repeat

 

}

DOWNLOAD
Copy and paste the above code in the Arduino IDE to program your Arduino.
Used Libraries:
Download the IRremote created by Ken Shirriff here:  https://github.com/z3t0/Arduino-IRremote
Fichier « Zip »
Once downloaded, just extract the content of the zip files inside your “arduino/libraries” folder.

pulseIn()
ARDUINO pulsIn()
 
 
Quand on mesure une impulsion, on doit d'abord définir sa polarité. Si le signal passe de 0 à 1 puis de 1 à 0, c'est une impulsion haute. Si le signal passe de 1 à 0 puis de 0 à 1, c'est une impulsion basse.
 
C'est un avion ? C'est un oiseau ? Non c'est pulseIn() !
Comme je l'ai précisé en introduction, mesurer une impulsion n'est pas aussi facile qu'on peut le croire.
 
Obtenir une mesure précise demande des timings précis. C'est pour cela qu'en général, quand on tente de réinventer la roue dans ce domaine, on finit avec des roues carrées.
Le framework Arduino fournit une fonction testée et éprouvée pour mesurer des impulsions (hautes ou basses) : pulseIn().
1 unsigned long pulseIn(broche, valeur);

2 unsigned long pulseIn(broche, valeur, timeout);

La fonction pulseIn() accepte au maximum trois paramètres et retourne un nombre entier long (unsigned long) correspondant à la durée de l'impulsion mesurée en microsecondes, ou 0 en cas d'erreur.
 
Le premier paramètre est le numéro de broche sur laquelle faire la lecture de l'impulsion.
 
Le second paramètre est la polarité de l'impulsion à mesurer. Si vous souhaitez mesurer une impulsion haute, il faut passer HIGH en paramètre à la fonction. Inversement, si vous souhaitez mesurer une impulsion basse, il faudra passer LOW en paramètre à la fonction.
 
Le troisième paramètre (optionnel) est la durée maximum en microsecondes de l'attente d'une impulsion avant la mesure. Si aucune impulsion n'arrive avant la fin du timeout, la fonction s'arrête et retourne 0.
 
N.B. Par défaut le timeout est d'une seconde !
 
En interne, la fonction pulseIn() fait trois choses :
  • Elle vérifie qu'une impulsion arrive dans le délai imparti.
  • Elle attend que le signal passe à l'état désiré et commence le comptage.
  • Elle attend que le signal repasse à l'état inverse de celui désiré pour arrêter le comptage.
 
N.B. La fonction pulseIn() calcule la durée de l'impulsion en comptant le nombre de tick d'horloge du processeur dans une boucle. C'est une solution bien plus fiable et précise que de tenter d'utiliser un timer quand celui-ci n'est pas conçu pour cela.
 
Quelques précisions importantes
  • Il y a entre une et deux microsecondes de délai avant le début effectif du comptage (juste le temps nécessaire pour appeler la fonction et préparer le comptage). Cela ne pose généralement pas de problème. Cependant, si vous avez un signal avec seulement quelques microsecondes de délai entre deux impulsions, cela peut poser des problèmes.
  • La fonction pulseIn() attends que le signal fasse une transition vers l'état désiré avant de commencer le comptage. Cela signifie que si vous mesurez une impulsion haute et que le signal est déjà à HIGH, il faudra attendre le passage à LOW puis de nouveau à HIGH pour le comptage commence. Ce comportement permet d'éviter de mesurer une impulsion déjà commencée. Cela a cependant pour conséquence de rendre impossible la mesure successive d'une impulsion haute puis basse ou inversement.
  • Il n'est pas possible de mesurer une impulsion en réponse à une interruption sur la même broche. Un cas d'erreur classique est de vouloir mesurer une impulsion dans la fonction appelée par attachInterrupt(). Quand l'interruption se déclenche, le signal a déjà changé d'état pour passer dans l'état désiré et la fonction pulseIn() va bloquer en attendant l'impulsion suivante.
  • Il est vivement déconseillé d'utiliser pulseIn() dans une interruption. Cela fonctionne (à peu près), mais c'est très bancal et cela va à l'encontre des bonnes pratiques de programmation qui veulent qu'une interruption doive être la plus courte / rapide possible.
  • La fonction pulseIn() ne donne des mesures fiables que si les interruptions sont désactivées. Quand les interruptions sont actives, le code en court d'exécution peut être mise en pause par une interruption pour gérer un événement, comme l'envoi d'un caractère sur le port série par exemple. Il est donc important d'entourer chaque appel à pulseIn() par un appel à noInterrupts() et un appel à interrupts() pour désactiver temporairement les interruptions.
  • Dans les versions récentes du framework Arduino (1.6.x et supérieur), une implémentation alternative de pulseIn() est disponible pour les cas où le reste du code fait usage d'interruptions qui ne peuvent être désactivés, même temporairement. Cette implémentation alternative utilise la fonction micros() en interne et elle est accessible via la fonction pulseInLong(). Les paramètres sont les mêmes que pulseIn(). Cette version a une plage de mesure de 10 µs ~ 3 minutes avec une précision de 4 µs (précision de micros()).
 
Exemple de code
 
L'exemple de code ci-dessous permet de lire la longueur d'une impulsion haute sur la broche D2 :
 
/** * Code d'exemple pour la fonction pulseIn() */ /** Broche d'entrée du signal */ const byte PIN_SIGNAL = 2; /** Fonction setup() */ void setup() { // Configure le port série pour l'exemple Serial.begin(115200); // Met la broche de signal en entrée pinMode(PIN_SIGNAL, INPUT); } /** Fonction loop() */ void loop() { // Mesure la durée de l'impulsion haute (timeout par défaut de 1s) noInterrupts(); unsigned long duration = pulseIn(PIN_SIGNAL, HIGH); interrupts(); // Affiche la durée de l'impulsion (en us) sur le port série Serial.println(duration); delay(1000); }
L'extrait de code ci-dessus est disponible en téléchargement sur cette page (le lien de téléchargement en .zip contient le projet Arduino prêt à l'emploi).
/**
* Code d'exemple pour la fonction pulseIn()
*/
 
/** Broche d'entrée du signal */
 
const byte PIN_SIGNAL = 2;
 
/** Fonction setup() */
 
void setup()
{
// Configure le port série pour l'exemple
 
Serial.begin(115200);
 
// Met la broche de signal en entrée
 
pinMode(PIN_SIGNAL, INPUT);
}
 
/** Fonction loop() */
 
void loop()
{
// Mesure la durée de l'impulsion haute (timeout par défaut de 1s)
noInterrupts();
unsigned long duration = pulseIn(PIN_SIGNAL, HIGH);
interrupts();
 
// Affiche la durée de l'impulsion (en us) sur le port série
 
Serial.println(duration); delay(1000);
}
 
 
L'extrait de code ci-dessus est disponible en téléchargement sur cette page (le lien de téléchargement en .zip contient le projet Arduino prêt à l'emploi).
pulseOut()
ARDUINO pulsOut()
 
 
Wiring/Arduino:
On the Wiring and Arduino boards, there is no pulseut command. However, there are two ways to create a series of pulses: analogWrite() or writing your own pulseout.
analogWrite() :
The pins marked PWM (pins 9 – 11 on Arduino, PWM 0 – 5 on Wiring) can be pulsed using the analogOut() command, like so:
analogWrite(pin, pulsewidth);
Pin refers to the pin you’re going to pulse
Pulsewidth is a value from 0 – 255. 0 corresponds to 0 volts, and 255 corresponds to 5 volts. Every change of one point changes the pseudo-analog output voltage by 5/255, or  0.0196 volts.
Write your own pulseOut :
Here’s an example of a pulseOut() function for Wiring/Arduino:
void setup()
{
// make pin 13 an output pin.
// You'll pulse the LED on this pin:
pinMode(13, OUTPUT);
}
void loop()
{
// read an analog input, 0 - 1023:
int pulse = analogRead(0);
// use that value to pulse an LED on pin 13:
pulseOut(13, pulse, HIGH);
}
 
void pulseOut(int pinNumber, int pulseWidth, int state)
{
// only pulse if the pulseWidth value
// is greater than 0:
if (pulseWidth > 0)
{
// if the pulse should be high, go high then low:
if (state == HIGH)
{
digitalWrite(pinNumber, HIGH);
delayMicroseconds(pulseWidth);
digitalWrite(pinNumber, LOW);
delayMicroseconds(pulseWidth);
}
// if the pulse should be low, go low then high:
else
{
digitalWrite(pinNumber, LOW);
delayMicroseconds(pulseWidth);
digitalWrite(pinNumber, HIGH);
delayMicroseconds(pulseWidth);
}
}
}
For most applications, it’s better to use the analogWrite() command, because the microcontroller maintains the PWM even after you give the command.
IR codes for SONY
ATTINY IR code for SONY
Offload IR decode to a dedicated Attiny85 for efficiency, simplicity, and reduced resources on the main microcontroller.
Schema_IR_ATTINY_1.jpg
Notes
Attiny85 core files used:

http://code.google.com/p/arduino-tiny/
You must select the correct "board" type... 
Why?
Using a dedicated Attiny85 microcontroller to monitor and decode the IR detector (MIM5383H4) frees the main uC from having to do this nasty and inefficient job.  This makes for nimble IR operation on the host microcontroller where only a serial port needs to be monitored for traffic which originates from the tiny85.
 
My implementation uses the Sony IR protocol which is available on almost every inexpensive Universal Remote Control.  The algorithm for this decode was developed and put in the public domain by Arduino Forum member pmalmsten.  Full links to his work is provided in my source code.  This is an Open Source implementation, so you can easily change the tiny85 to decode NEC or other remote protocols by changing the decode algorithm - but you are on your own for this effort; however there are many IR decode algorithms freely available for the searching on Google.
 
The main program is more efficient and requires less resources because the IR polling and decoding is eliminated and the host simply receives the decoded digits and commands on the serial port at 9600 BAUD in my example.  This solution is also microcontroller agnostic: I have used it for AVR and for PIC.  You can even feed the serial output of the ATtiny85 to your PC over a USB/serial converter and host software on the PC to do magic stuff.
 
On the Arduino, all that is necessary is a single statement in the loop():
if (Serial1.available() > 0)    >If  nothing is in queue, then the host Arduino microcontroller does not need to be concerned about IR messages.  It cannot get much simpler!
 
Resources
 
I have a full write-up of this technique on the main Arduino.cc Forum:
http://forum.arduino.cc/index.php?topic=139907.0
 
There is also code on the link which implements a full DS3234 setup using an Arduino Mega2560 and a serial OLED display.  The code is rather lengthy as it is the skeleton for an engine monitoring system for an Europa ultralight experimental plane, but the routines are easy to spot.  Feel free to rip this out and use it in your own code or improve it and repost to the Arduino Forum for everyone to share.
 
Enjoy your next Arduino project by easily implementing IR into your code without fear of over burdening your microcontroller.
 
 
 

/* IR remote control (Sony) detection for Arduino, M. Burnette

Binary sketch size: 2,794 bytes (of a 8,192 byte maximum)

 

20130103 MRB Modified for interface to Mega2560

Europa codebase for menu system

 

20121230 MRB Modified for Tiny85 Google Tiny library

Tiny85 Internal RC 16MHz

 

20121230 MRB modifications to adapt to numeric input, avoid dupes,

and to generally "behave" consistently

Used with Electronic Goldmine IR detector MIM 5383H4

http://www.goldmine-elec-products.com/prodinfo.asp?number=G16737

IR detector:

Pin 1: To pin D4 on Arduino ATtiny85

Pin 2: GND

Pin 3: 5V through 33 Ohm resistor

 

This is based on pmalmsten's code found on the Arduino forum from 2007: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1176098434/0

*/

 

// Pins 2/3 used for Software serial

int irPin = 4; //Sensor pin 1 wired to Arduino's pin D4

int statLED = 0; //Toggle the status LED every time Power is pressed

int start_bit = 2200; //Start bit threshold (Microseconds)

int bin_1 = 1000; //Binary 1 threshold (Microseconds)

int bin_0 = 400; //Binary 0 threshold (Microseconds)

 

void setup()

{

pinMode(statLED, OUTPUT);

digitalWrite(statLED, LOW);

 

pinMode(irPin, INPUT);

Serial.begin(9600);

Serial.println("IR/Serial Initialized: ");

}

 

void loop()

{

int key = getIRKey(); //Fetch the key

if(key != 0) //Ignore keys that are zero

{

switch(key)

{

case 128: Serial.print("1"); break;

case 129: Serial.print("2"); break;

case 130: Serial.print("3"); break;

case 131: Serial.print("4"); break;

case 132: Serial.print("5"); break;

case 133: Serial.print("6"); break;

case 134: Serial.print("7"); break;

case 135: Serial.print("8"); break;

case 136: Serial.print("9"); break;

case 137: Serial.print("0"); break;

case 144: Serial.print("A"); break; // CH Up

case 145: Serial.print("B"); break; // CH Down

case 146: Serial.print("C"); break; // VOL Right

case 147: Serial.print("D"); break; // VOL Left

case 148: Serial.print("E"); break; // Mute

case 165: Serial.print("F"); break; // AV/TV

case 149: Serial.print("P"); // Power == MENU ACTIVE

//This toggles the statLED every time power button is hit

if(digitalRead(statLED) != 1)

digitalWrite(statLED, HIGH);

else

digitalWrite(statLED, LOW);

break;

 

//default: Serial.println(key); // for inspection of keycode

}

 

delay(400); // avoid double key logging (adjustable)

}

}

 

int getIRKey()

{

int data[12];

int i;

while(pulseIn(irPin, LOW) < start_bit); //Wait for a start bit

for(i = 0 ; i < 11 ; i++)

data[i] = pulseIn(irPin, LOW); //Start measuring bits, I only want low pulses

for(i = 0 ; i < 11 ; i++) //Parse them

{

if(data[i] > bin_1) //is it a 1?

data[i] = 1;

else if(data[i] > bin_0) //is it a 0?

data[i] = 0;

else return -1; //Flag the data as invalid; I don't know what it is! Return -1 on invalid data

}

int result = 0;

for(i = 0 ; i < 11 ; i++) //Convert data bits to integer

if(data[i] == 1) result |= (1<<i);

return result; //Return key number

}

ATTINY programmer shield
ATTINY PROGRAMMER SHIELD
ATtiny85-Programmer-Shield-1.png
ATtiny85-Programmer-Shield-2.png
ATtiny85-Programmer-Shield-3.png
ATtiny85-Programmer-Shield-4.png
ATtiny85-Programmer-Shield-5.png
ATtiny85-Programmer-Shield-6.png
ATtiny85-Programmer-Shield-7.png
ATtiny85-Programmer-Shield-8.png
HC05 - commandes AT
HC-05 : commandes « AT »
 
 
Cet article n'est pas un cours sur les commandes « AT ». Il y a de très bons articles pour cela sur le net (ICIICIICI).
 
Le problème posé est le suivant :
« Si on utilise plusieurs modules HC-05 ou HC-06 pour des télécommandes
« ANDROÏD⇒ BLE ⇒ ARDUINO », comment les distinguer sur l'appareil ANDROÏD qui va les commander ? »
 
En effet, lorsqu'on veut « associer » un module HC-05 avec un appareil ANDROÏD, on le voit apparaître sous le nom « HC-05 ».
Mais les modules HC-05 apparaissent tous sous ce même nom générique « HC-05 » !
Aïe !
... et on ne sait plus qui est qui.
Et surtout on ne sait plus quel HC-05 est déjà associé ou non avec l'appareil ANDROÏD, ni à quel usage il est destiné.
emoticone_confuse.jpg
 
 
La solution :
Avant toute tentative d'association, changer le nom générique « HC-05 » de chaque module par un nom explicite.
C'est sous ce nouveau nom que le module BLE sera vu par chaque appareil ANDROÏD avec lequel on cherchera à l'associer.
Ceci implique que le nouveau nom du HC-05 doit être écrit dans le module HC-05 lui-même.
 
Note :
Rien à voir donc avec la possibilité offerte par les appareils ANDROÏD de « Changer le nom » d'un module.
 
En effet, cette fonction « Changer le nom » nous permet juste de donner, après coup, au HC-05 un nom distinctif « local » qui n'est valable que sur l'appareil ANDROÏD sur lequel on opère le changement de nom.
Un autre appareil ANDROÏD ne verra pas ce nom « local » puisque ce nom n'est pas écrit dans le HC-05 lui-même.
 
 
Matériel et schéma
 
On va utiliser un petit ensemble comme celui-ci :
hc-05_test_3b.jpg
  • un ARDUINO UNO ou NANO  qui contient le programme pour gérer les commandes « AT » ;
  • un shield pour disposer facilement des connexions nécessaires entre l'ARDUINO, le HC-05 et l'ordinateur ;
  • un programme ARDUINO.
HC-05_test_5.png
 
Shéma
HC-05 ⇒  NANO
 
J'ai utilisé des connecteurs « Dupont » pour faire un montage volant, mais on peut tout aussi bien utiliser une plaque d'essai pour connecter rapidement le HC-05.
L'intérêt d'utiliser un shield comme celui ci-dessous, c'est que chaque broche de l'ARDUINO est associée à un «+5V» et à un «0V».
hc-05_test_2b.jpg
HC-05_test_2a.jpg
HC-05_test_1.jpg
 
Sketch ARDUINO
Télécharger ICI
Quelques points très importants :
  • il est préférable d'opérer le changement de nom avant toute association du HC-05 avec un appareil ANDROÏD ;
  • pour que le HC-05 soit en mode « commandes AT », il faut appuyer sur le petit bouton situé en face de la broche « EN » ou « Key » avant que le HC-05 sous mis tension. On relâche ce bouton dès que la tension est établie ⇒ la LED du HC-05 doit alors clignoter lentement (rythme de 2 secondes).
    J'ai un peu galéré avant de trouver cette info sur le net.
    Info que je me suis donc empressé de reporter sous forme de commentaire dans le sketch pour vous éviter de passer à côté.
  • le HC-05 est connecté sur les broches 2 et 3 de l'ARDUINO, et pas sur les broches 0 et 1 qui, elles, sont réservées à la communication série avec le moniteur ;
  • le moniteur de l'IDE ARDUINO doit être réglé sur 57600 bauds et « Les deux , NL et CR » pour que les commandes « AT » soient reconnues par le HC-05.

Les commandes « AT » sont décrites dans ce document.
 
 
Avis personnel
Compte-tenu du prix très modeste d'un ARDUINO (NANO ou UNO) et d'un shield de connexion, j'ai décidé de conserver ce petit ensemble en ordre de marche, dédié uniquement à l'usage décrit ci-dessus.
 
Il m'a déjà rendu beaucoup de services.
SlowMotionServo
Librairie SlowMotionServo

 

 

Le 3 mars 2018
. Par : Jean-Luc
Mouvoir lentement un organe mécanique revient fréquemment en modélisme ferroviaire. On peut citer les aiguillages, les signaux mécaniques, les passages à niveau ou bien encore les portes de remises. Parmi les actionneurs possibles, on trouve les moteurs à courant continu, les moteurs pas à pas et les servomoteurs.
Ces derniers sont les plus simple à commander avec un Arduino car ils ne nécessitent aucune électronique supplémentaire. Les servomoteurs ont fait l’objet de plusieurs articles sur Locoduino, principalement « Les différents types de mouvements d’un servomoteur » et « La bibliothèque Servo ». Nous vous présentons maintenant une nouvelle bibliothèque réalisée par l’auteur et permettant de déplacer lentement plusieurs servomoteurs selon des trajectoires précises.
 
Après la réalisation du logiciel de pilotage de servomoteurs destiné à la commande d’actionneurs d’aiguillages, voir « Manœuvre des aiguilles avec des servomoteurs » j’ai voulu m’attaquer à la manœuvre de portes de remises et de barrières de passage à niveau. Les mouvements à accomplir sont plus complexes mais aussi plus visuels. La technique doit donc être différente.
 
Le mouvement du servomoteur pour actionner un aiguillage est linéaire, c’est à dire que l’évolution de l’angle du palonnier au cours du temps est une droite. Cela convient tout à fait dans ce cas mais pour animer le reseau, d’autres mouvements sont nécessaires. Par exemple, l’ouverture d’une porte de remise aura une phase d’accélération, la porte est poussée, une phase de décélération, la porte continue sur son erre et les frottements la ralentisse puis une phase de rebond où la porte revient en arrière avec un mouvement amorti. Il est donc nécessaire de définir le mouvement du servomoteur comme une trajectoire. De cette manière tout est permis.
 
La bibliothèque SlowMotionServo est construite pour cela. Elle permet de piloter plusieurs servomoteurs simultanément et, pour chacun de ces servomoteurs, de définir une trajectoire, en fait deux trajectoires, une pour le mouvement du palonnier dans le sens trigonométrique et une pour le mouvement dans le sens horaire.
 
La vitesse de parcours de ces deux trajectoires est également réglable.
 
La position du servomoteur est normalisée sous forme d’un nombre à virgule entre 0.0 et 1.0, 0.0 correspond à la largeur d’impulsion de commande minimum et 1.0 à la largeur maximum.
 
Installer la bibliothèque
 
SlowMotionServo est disponible via le gestionnaire de bibliothèque de l’IDE. Dans le menu Croquis, sélectionnez Inclure une bibliothèque puis Gérer les bibliothèques. Dans la case de recherche en haut à droite de la fenêtre qui apparaît, tapez SlowMotionServo.
Mise en œuvre rapide
Commençons par une utilisation simple. Nous n’avons qu’un seul servomoteur à piloter. Commençons par un simple mouvement linéaire. Tout d’abord, comme pour tout autre bibliothèque, il faut inclure SlowMotionServo et Servo, bibliothèque sur laquelle repose SlowMotionServo. Sélectionner dans le menu Croquis puis Inclure une bibliothèque puis SlowMotionServo ajoutera ces deux inclusions dans votre sketch.
  1. #include <Servo.h>
  2. #include <SlowMotionServo.h>
Ensuite, nous allons créer un objet de la classe SMSLinear.
  1. SMSLinear monServo;
Dans setup, nous spécifions la broche par laquelle le servo est commandé, ici la broche 2.
  1. void setup()
  2. {
  3. monServo.setPin(2);
  4. }
Il nous faut également une variable qui va contenir alternativement 0.0 et 1.0 pour fixer la position cible du servomoteur. Nous initialisons cette variable à 0.0.
  1. float positionCible = 0.0;
 
Dans loop, nous devons appeler la fonction qui assure l’actualisation de la position du servo et, quand le servo est à l’arrêt, c’est à dire que sa position cible est atteinte, nous changeons cette position cible.
  1. void loop()
  2. {
  3. SlowMotionServo::update(); /* actualisation de la position */
  4. if (monServo.isStopped()) {
  5. positionCible = 1.0 - positionCible;
  6. monServo.goTo(positionCible);
  7. }
  8. }
 
Trois trajectoires sont livrées, une trajectoire linéaire, SMSLinear, qui convient pour les aiguillages :
smslinear-de8d3.png
Une trajectoire avec une phase d’accélération et de décélération, SMSSmooth :
smssmooth-c6a7a.png
... et une trajectoire avec dans une direction une phase d’accélération et de décélération suivi d’un amorti, la courbe rouge, et dans l’autre direction une phase d’accélération et de décélération seule, la courbe bleue sur le graphe qui suit, SMSSmoothBounce :
smssmoothbounce-b1e4e.png
Cette dernière trajectoire convient pour les portes de remise. Il est bien évidemment possible de définir ses propres trajectoires.
Changer les positions minimum et maximum
Nous avons vu que 0.0 correspond à la position minimum et que 1.0 correspond à la position maximum. Par défaut, ces positions correspondent respectivement à des largeurs d’impulsion de 1000µs et 2000µs, c’est à dire les valeurs minimum et maximum recommandées par la bibliothèque Servo. Il est bien évidemment possible de les changer mais faites attention de rester dans les limites permises par vos servomoteurs.
 
setMin (min)
Définit l’angle minimum du servo. L’angle est exprimé en son équivalent en microsecondes. La valeur peut varier de 544 à 2400. Une valeur inférieure à 544 sera ramenée à 544 et une valeur supérieure à 2400 sera ramenée à 2400. Si la valeur est inférieure à l’angle minimum, elle est ramenée à l’angle minimum.
 
setMax (max)
 
Définit l’angle maximal du servo. L’angle est exprimé en son équivalent en microsecondes. La valeur peut aller de 544 à 2400. Une valeur inférieure à 544 sera ramenée à 544 et une valeur supérieure à 2400 sera ramenée à 2400. Si la valeur est supérieure à l’angle maximum, elle est ramenée à l’angle maximum.
 
setMinMax (min, max)
 
Définit les angles minimum et maximum du servo. L’angle est exprimé en son équivalent en microsecondes. La valeur peut varier de 544 à 2400. Une valeur inférieure à 544 sera ramenée à 544 et une valeur supérieure à 2400 sera ramenée à 2400. Si l’angle minimum est supérieur à l’angle maximal, les deux angles sont définis sur la valeur moyenne . Par exemple, si vous définissez l’angle minimum sur 2000 et l’angle maximal sur 1000, les deux angles seront définis sur 1500, ce qui se traduira par une impossibilité de mouvement.
 
Changer la vitesse du mouvement et le sens du mouvement
 
Par défaut, quelques soient les angles minimum et maximum, les trajets de l’angle minimum à l’angle maximum et inversement sont effectués en 10s. Les vitesses peuvent être réglées via les fonctions suivantes.
 
setMinToMaxSpeed(vitesse)
 
Règle la vitesse du servo lorsqu’il se déplace de l’angle minimum à l’angle maximum. la vitesse est un nombre à virgule. Une vitesse de 1.0 correspond à une durée de 10s.
 
setMaxToMinSpeed(vitesse)
 
Règle la vitesse du servo lorsqu’il se déplace de l’angle maximum à l’angle minimum. la vitesse est un nombre à virgule. Une vitesse de 1.0 correspond à une durée de 10s.
 
setSpeed(vitesse)
 
Règle la vitesse du servo lorsqu’il se déplace de l’angle minimum à l’angle maximum et de l’angle maximum à l’angle minimum. la vitesse est un nombre à virgule flottante. Une vitesse de 1.0 correspond à un 10s en déplacement.
 
setReverted(sens)
Par défaut, sens, un booléen, est false et les trajectoires correspondent aux graphiques ci-dessus. Si sens est mis à true, le mouvement est inversé selon un axe de symétrie situé à t=0.5. Par exemple, la trajectoire SMSSmoothBounce devient :
smssmoothbouncerev-89f5a.png
Déclenchement du mouvement
Les fonctions suivantes permettent de mouvoir le servomoteur.
 
setInitialPosition(position)
 
Définit la position initiale du servo. La position est un nombre à virgule flottante allant de 0.0 à 1.0. Si la valeur est supérieure à 1.0, elle est ramenée à 1.0 et si elle est inférieure à 0.0, il est ramenée à 0.0
 
goTo(position)
 
Va à la position spécifiée en suivant la trajectoire. La position est un nombre à virgule flottante allant de 0.0 à 1.0. Si la valeur est supérieure à 1.0, elle est ramenée à 1.0 et si elle est inférieure à 0.0, il est ramenée à 0.0
 
goToMin()
 
Équivalent à goTo(0.0)
 
goToMax()
 
Équivalent à goTo(1.0)
 
setDetachAtMin(detache)
 
detache est un booléen. Si true, le servo est détaché lorsque la position minimum est atteinte. Le servo n’est plus piloté. Ceci est utile lorsque le servo doit pousser contre une force de rappel élastique. Si false, le servo continue à être piloté.
 
setDetachAtMax(detache)
 
detache est un booléen. Si true, le servo est détaché lorsque la position maximum est atteinte. Le servo n’est plus piloté. Ceci est utile lorsque le servo doit pousser contre une force de rappel élastique. Si false, le servo continue à être piloté.
 
setDetach(detache)
 
detache est un booléen. Si true, le servo est détaché lorsque la position minimum ou maximum est atteinte. Le servo n’est plus piloté. Ceci est utile lorsque le servo doit pousser contre une force de rappel élastique. Si false, le servo continue à être piloté.
 
isStopped()
 
retourne true si le servo est arrêté, false si il est en mouvement.
 
Les autres fonctions
 
setPin(pin)
 
Spécifie la broche à laquelle le servo est branché.
 
SlowMotionServo::setDelayUntilStop(delai)
 
Cette fonction de classe définit le délai entre le moment où les servos atteignent leur position minimum ou maximum et le moment où ils sont détachés. Comme la mécanique est toujours en retard par rapport au programme, détacher immédiatement les servos les empêcherait d’atteindre leur position mécanique. Ceci est défini une fois pour tous les servos et utilisé uniquement pour les servos et les positions pour lesquelles setDetach(true) est spécifié.
 
SlowMotionServo::update()
 
Met à jour les positions de tous les servos. Cette fonction de classe doit être appelée dans loop(). Il ne faut pas que le temps d’exécution de loop() soit trop long sinon le mouvement du ou des servomoteurs se fera par à-coups [1]. Il faut notamment bannir delay().
Comment définir ses propres trajectoires
Pour ce faire, vous devez hériter de la classe SlowMotionServo et redéfinir les fonctions membres slopeUp et slopeDown. Prenons la classe SMSSmooth comme exemple :
  1. class SMSSmooth : public SlowMotionServo
  2. {
  3. public:
  4. virtual float slopeUp(float time);
  5. virtual float slopeDown(float time);
  6. float slope(float time) { return (1.0 - cos(time * PI))/2.0; }
  7. };
 
Comme les trajectoires sont les mêmes de min à max et max à min, nous définissons une nouvelle fonction membre, slope, qui définit la trajectoire. Cette fonction est appelée par slopeUp et slopeDown :
  1. float SMSSmooth::slopeUp(float time)
  2. {
  3. return slope(time);
  4. }
  5. float SMSSmooth::slopeDown(float time)
  6. {
  7. return slope(time);
  8. }
 
Un exemple concret
 
Pour aller plus loin que le petit exemple déjà présenté, je vous propose une petite application permettant de gérer les portes d’une remise à locomotives au moyen d’un bouton poussoir. Le comportement est simple : si les portes sont toutes les deux fermées, une pression sur le bouton les ouvre. Si les portes sont toutes les deux ouvertes, une pression sur le bouton les ferme. Si au moins l’une est en mouvement une pression sur le bouton est sans effet.
 
Afin de permettre une réutilisation facile et une réplication des double-portes, nous allons définir une class Remise va regrouper les deux servos et le bouton ainsi que la fonction les initialisant et la fonction faisant fonctionner le système. Il s’agit en fait de l’encapsulation du code de l’exemple PushButton2Servos livré avec la bibliothèque. Voici la classe Remise :
  1. class Remise {
  2. private: SMSSmoothBounce mPorteDroite;
  3. private: SMSSmoothBounce mPorteGauche;
  4. private: Bounce mBoutonOverture;
  5. private: bool mPosition; /* false = fermé, true = ouvert */
  6. public: void demarre(const byte pinBouton, const byte pinServoPorteDroite, const byte pinServoPorteGauche);
  7. public: void gereRemise();
  8. };
 
On y trouve nos deux servos de type SMSSmoothBounce et le bouton [2]. On a également une variable booléenne, mPosition permettant de mémoriser si les portes sont en position ouverte ou fermée. Enfin, la fonction demarre permet d’initialiser tout ce petit monde et la fonction gereRemise gère le bouton et lance le mouvement si il est enfoncé et que les portes sont stoppées.
 
La fonction demarre
 
Cette fonction procède donc aux intialisations. La broche du bouton est programmée en entrée avec résistance de tirage à 5V, l’objet mBouton est accroché à sa broche et son intervalle de rafraichissement est fixé. Les valeurs minimum et maximum des deux portes sont fixées avec une ouverture légèrement supérieure à 90°. Les valeurs sont à affiner selon vos servos. La vitesse est fixée à 1.7, cette valeur est à régler selon vos goûts. Le mouvement de la porte gauche est inversé par rapport au mouvement de la porte de droite. Les positions initiales sont fixées à 0.1 afin qu’il y ait un mouvement au démarrage pour fermer les portes (les deux goTo(0.0) à la fin de demarre). En effet, il faut que la position initiale soit différente du premier mouvement demandé, sinon aucun mouvement n’aura lieu. Enfin, les deux servos sont accrochés à leur broche respectives.
  1. void Remise::demarre(const byte pinBouton, const byte pinServoPorteDroite, const byte pinServoPorteGauche)
  2. {
  3. pinMode(pinBouton, INPUT_PULLUP);
  4. mBoutonOverture.attach(pinBouton);
  5. mBoutonOverture.interval(5); /* rafraichissement toutes les 5ms */
  6. mPorteDroite.setMin(700);
  7. mPorteDroite.setMax(1800);
  8. mPorteDroite.setSpeed(1.7);
  9. mPorteGauche.setMin(1100);
  10. mPorteGauche.setMax(2200);
  11. mPorteGauche.setSpeed(1.7);
  12. mPorteGauche.setReverted(true); /* La porte gauche a un mouvement inverse */
  13. mPorteDroite.setInitialPosition(0.1);
  14. mPorteGauche.setInitialPosition(0.1);
  15. mPorteDroite.setPin(pinServoPorteDroite);
  16. mPorteGauche.setPin(pinServoPorteGauche);
  17. mPosition = false;
  18. /* ferme les porte au démarrage */
  19. mPorteDroite.goTo(0.0);
  20. mPorteGauche.goTo(0.0);
  21. }
 
La fonction gereRemise
 
Cette fonction lit le bouton et, si aucune des portes n’est en mouvement et si le bouton a été enfoncé, fixe une position cible en fonction de la position courante. Voici cette fonction :
  1. void Remise::gereRemise()
  2. {
  3. mBoutonOverture.update(); /* met à jour l'état du bouton */
  4. if (mPorteDroite.isStopped() && mPorteGauche.isStopped())
  5. {
  6. /* si un mouvement était en cours, il est terminé */
  7. if (mBoutonOverture.fell()) {
  8. /* appui sur le bouton, on démarre le mouvement */
  9. if (mPosition) {
  10. /* la remise est ouverte, la cible pour la fermer est 0.0 */
  11. mPorteDroite.goTo(0.0);
  12. mPorteGauche.goTo(0.0);
  13. mPosition = false;
  14. }
  15. else {
  16. /* la remise est fermée, la cible pour l'ouvrir est 1.0 */
  17. mPorteDroite.goTo(1.0);
  18. mPorteGauche.goTo(1.0);
  19. mPosition = true;
  20. }
  21. }
  22. }
  23. }
 
Le sketch
Tout d’abord, nous créons un objet de type Remise :
  1. Remise remise1;
 
Ensuite nous déclarons des constantes correspondant aux broches où sont connectés le bouton et les servos :
  1. const byte pinServoDroitRemise1 = 4;
  2. const byte pinServoGaucheRemise1 = 3;
  3. const byte pinBoutonRemise1 = 5;
 
Dans setup, nous initialisons la remise :
  1. void setup()
  2. {
  3. remise1.demarre(pinBoutonRemise1, pinServoDroitRemise1, pinServoGaucheRemise1);
  4. }
 
Enfin dans loop, nous appelons SlowMotionServo::update() pour actualiser la position des servos et nous appelons gereRemise() pour saisir les ordres de l’utilisateur et lancer le mouvement des portes :
  1. void loop()
  2. {
  3. SlowMotionServo::update();
  4. remise1.gereRemise();
  5. }
Petit lexique
Petit lexique

 

 

Petit lexique pour faciliter la lecture
BLE pour Bluetooth Low Energy. Mode de transmission bidirectionnelle de données sur de courtes distances (de l'ordre de 20 mètres sans obstacle).
Le module HC-05 utilisé dans cette application est un transmetteur BLE.
Il en existe d'autres, dont le HC-06, parfaitement interchangeable avec le HC-05 (dans le cas présent).
 
ARDUINO : nom générique d'un ensemble de cartes électroniques «open source» à micro-contrôleurs programmés en langage C++. Ces cartes disposent d'un nombre important d'entrées/sorties. De nombreux professionnels proposent des gammes de capteurs et d'actionneurs pour ces cartes.
UNO et NANO sont deux des modèles de cartes de la série ARDUINO.
 
Sketch ARDUINO : c'est ainsi que l'on désigne le texte du programme en langage C++ destiné à être compilé puis téléversé dans l'ARDUINO.
 
Shield : cartes de fonctions qui s'embrochent directement sur la carte ARDUINO, permettant de constituer, par empilage, des ensembles électroniques programmés compacts et extrêmement puissants.
 
ANDROÏD : système d'exploitation «ouvert» qui équipe actuellement une majorité des smartphones et tablettes.

Ce système est basé sur un noyau Linux. Il est actuellement développé par Google.
Ce système s'est diversifié dans les objets connectés : voitures, télévisions, ordinateurs...
Il détient 80% des parts de marché.
 
Smartphone, ordiphone ou téléphone intelligent, est un téléphone mobile disposant en général d'un écran tactile, d'un appareil photographique numérique, des fonctions d'un assistant numérique personnel et de certaines fonctions d'un ordinateur portable, et dans le cas qui nous intéresse, il gère les communications Bluetooth.
 
Phablette : c'est un smartphone dont l'écran est d'une taille intermédiaire entre celui des smartphones stricto sensu, et celui des tablettes tactiles.
C'est une tablette avec en plus la fonction « téléphone ».
 
IDE : Integrated Development Environment.
Logiciel comportant l'ensemble des outils et fonctions pour la programmation d'un micro-contrôleur comme celui de l'ARDUINO, par exemple.
 
Micro-contrôleur : circuit intégré capable d'exécuter des actions conformément au programme qu'on lui a injecté (téléversé).
Plus limité en performances qu'un micro-processeur d'ordinateur, il est destiné à des applications embarquées, sous un volume bien plus restreint que celui d'un ordinateur. (Il est plus lent et n'a pas de système d'exploitation).
 
MIT App Inventor 2 :
App Inventor pour Android est une application développée par Google. Elle est actuellement entretenue par le Massachusetts Institute of Technology (MIT).
Elle simplifie le développement des applications sous Android qu'elle rend accessible même pour les novices et ceux qui ne sont pas familiers avec les langages de programmation. Elle est basée sur une interface graphique similaire à Scratch et à celle de StarLogo TNG (en). Grâce à son interface entièrement graphique et à l'absence totale de ligne de code, elle est particulièrement adaptée à l'initiation des enfants à la programmation, et ce dès l'école primaire.
N.D.L.R. même quand on est un enfant de 70 ans, ça marche aussi ;-) .
Google publie l'application le 15 décembre 2010 et met fin à son activité le 31 décembre 2011. Dès l'été 2011, Google travaille sur un projet similaire Blockly, développé cette fois en javascript. Depuis le retrait de Google, c'est le centre d'études mobiles au MIT qui gère le support technique de cette application sous le nouveau nom "MIT App Inventor". (Texte extrait de l'article de Wikipedia).
Programme pour SERVO
Programme pour SERVO
Les bases
Les connaissances nécessaires au pilotage d’un servomoteur sont :
Servo_H.png

 

 

Librairie <Servo.h>
 
Fonctions de la librairie <Servo.h>
  • attach()
  • write()
  • writeMicroseconds()
  • read()
  • attached()
  • detach()
 
Code Source simple
Le programme de contrôle en quelques lignes
#include <Servo.h>
 
Servo monServo;
 
void setup()
{
// Attacher la pin 9 à l'objet servo.
// ATTN: le code initialise l'angle à 90 degrés par défaut.
monServo.attach(9);
}
 
void loop()
{
// Assigne un angle de 53 degrés
monServo.write( 53 );
delay( 2000 );
 
// Passer de 0 a 180 degrés par angle de 10 degrés
for( int iAngle=0; iAngle<= 180; iAngle+=10 )
{
monServo.write(iAngle);
delay( 50 );
}
}
______________
Un exemple plus avancé
Voici le code, une version plus complète d'un programme contrôlant un servo-moteur.
 
Il démontre clairement la capacité d'Arduino à contrôler finement la position d'un servo-moteur.
 
/* * Commande d'un servo moteur en plusieurs séquences.
* Clignotement de la Led onBoard:
* - rapide en début de programme.
* - lente en entre les séquences.
* - fixe en fin de programme
*
* Commande servo à l'aide de servo.h et
* seulement sur les pin 9 ou pin 10.
*
*/
 
#include <Servo.h>
 
Servo monServo;
int pos = 0;
 
const int pinLed = 13; // Led sur le board
const long blinkTimeMs = 2000; // temps de clignotement de la led (2 sec)
 
const int FAST = 50; // interval entre deux clignotement (rapide)
const int SLOW = 150; // interval entre deux clignotement (lent)
const int FIXED = -1; // valeur spécial pour éclairage continu
 
void setup()
{
pinMode( pinLed, OUTPUT );
// Attacher la pin 9 à l'objet servo.
// ATTN: le code initialise l'angle à 90 degrés par défaut.
monServo.attach(9);
// remettre l'angle à 0 degrés
monServo.write( 0 );
}
 
void loop()
{
// Faire clignoter led 13 sur le board.
// Démarrage de séquence --> clignotement rapide
blinkBoardLed( FAST );
 
// Passer de 0 a 180° par angle de 10 degré
for( int iAngle=0; iAngle<= 180; iAngle+=10 )
{
monServo.write(iAngle);
delay( 250 );
}
 
// Clignotement lent entre deux séquences
blinkBoardLed( SLOW );
// Angle décroissant progressif
for( int iAngle = 180; iAngle>=0; iAngle-- )
{
monServo.write( iAngle );
delay( 10 );
}
 
// Clignotement lent entre deux séquences
blinkBoardLed( SLOW );
 
// Angle arbitraire de 45 degrés
monServo.write( 45 );
 
// Find de séquence -> eclairage fixe
blinkBoardLed( FIXED );
}
/* Fait clignoter la led 13 sur le board pendant 2 secondes
*
* interval: Interval de clignotement. -1 pour fixe.
*/
 
void blinkBoardLed( int interval )
{
long startMillis = millis();
// temps que pas 2 sec d'écoulée
while( (millis() - startMillis) < blinkTimeMs )
{
switch( interval )
{
case -1 : // Cas spécial, allumage fixe
digitalWrite( pinLed, HIGH );
delay( blinkTimeMs ); // attendre le temps total
digitalWrite( pinLed, LOW );
break;
default:
// faire clignoter
digitalWrite( pinLed, HIGH );
delay( interval );
digitalWrite( pinLed, LOW );
delay( interval );
} // eof Case
} // eof While
}
__________
Programme sans la librairie <servo.h>
(D'après OpenClassrooms)
/*
Commande de servo-moteur par impulsion
Nanomaître 2015
Le servo est connecté au pin 8 de l'arduino
*/
int periode=20000;// période entre chaque début d'impulsion en microsecondes
int pinServo=8; // variable pour le pin connecté à la commande du servo

void setup() {
  pinMode(pinServo,OUTPUT);// on prépare le pin en mode OUTPUT
  digitalWrite(pinServo,LOW); // on l'initialise à l'état bas
}

//boucle principale
void loop() {
  for (int angle=0;angle<=180;angle+=20){//on fait varier l'angle de 0 à 180° par tranche de 20°
    setAngle(angle);// on appelle la fonction setAngle définie plus bas
  }
}

//fonction setAngle pour envoyer les impulsions
void setAngle(int a){
  int duree=map(a,0,179,1000,2000);// on transforme l'angle en microsecondes et on stocke dans la variable duree
  digitalWrite(pinServo,LOW);//on met le pin à l'état bas
 
  // la boucle qui suit est nécessaire
  // pour laisser le temps au servo d'aller à sa position
  for (int t=0;t<300;t++){
    digitalWrite(pinServo,HIGH);// on envoie l'impulsion
    delayMicroseconds(duree); // pendant la bonne durée
    digitalWrite(pinServo,LOW); // on stoppe l'impulsion
    delayMicroseconds(periode-duree); // on attend le temps restant pour atteindre la période
  }
}
Envoyez et testez ! Si tout se passe bien, le servo prend une position extrême (0°) puis se déplace par tranche de 20°, puis lorsqu'il atteint les 180°, il revient à la position de départ et recommence.
Soudure à l'arc
Soudure à l'arc
SIMULATEUR DE SOUDURE à L'ARC pour ATTINY 45/85
sur le site de locoduino.org

par Christian Bézanger
Liste des composants nécessaires pour le chenillard
 
Un ATtiny45 que vous aurez programmé.
Une DEL blanche haute intensité.
Une résistance de 220 Ω.
 
Programme pour l’ATtiny45
 
Le programme pour le module Uno publié dans l’article Simulateur de soudure à arc a été modifié pour l’adapter à un ATtiny45 en choisissant la broche 3 pour brancher la DEL et sa résistance de limitation (au lieu de 13) et la broche analogique 2 pour la fonction randomSeed (au lieu de 2). Téléchargez ce programme puis téléversez-le dans une puce ATtiny en suivant la procédure décrite dans l’article Le microcontrôleur ATtiny45 (2).
 
  1. /* Ce programme commande une LED blanche pour simuler un poste de soudure à l'arc.
  2.   Il fait appel à la fonction random qui génère des nombres aléatoires.
  3.   Duree_flash est la durée d'un flash. Duree_int est la durée entre deux flashes.
  4.   Duree_flash et Duree_int forment un événement.
  5.   Nbre_even est le nombre d'événements au cours d'un cycle de soudure.
  6.   P_repos est la durée entre deux cycles de soudure.
  7.   Toutes ces données sont aléatoires mais bornées entre une valeur minimum et une
  8.   valeur maximum. En jouant sur l'intervalle, on peut simuler au mieux l'effet de
  9.   soudure à l'arc. Broche est la broche sur laquelle la LED est connectée, ici broche 3.
  10. */
  11. // Initialisation des variables
  12. byte Broche = 3 ;
  13. long Duree_flash ;
  14. long Duree_flash_mini = 10 ;
  15. long Duree_flash_maxi = 101 ;
  16. long Duree_int ;
  17. long Duree_int_mini = 10 ;
  18. long Duree_int_maxi = 31 ;
  19. long Nbre_even ;
  20. long Nbre_even_mini = 10 ;
  21. long Nbre_even_maxi = 21 ;
  22. long P_repos ;
  23. long P_repos_mini = 1500 ;
  24. long P_repos_maxi = 7001 ;
  25. long i ;
  26.  
  27. // Fonction d'initialisation
  28. void setup ()
  29. {
  30. randomSeed (analogRead (2)) ;
  31. pinMode (Broche, OUTPUT) ;
  32. }
  33.  
  34. // Corps du programme
  35. void loop ()
  36. {
  37. Nbre_even = random (Nbre_even_mini, Nbre_even_maxi) ;
  38. for (i = 1 ; i <= Nbre_even ; i++)
  39. {
  40. Duree_flash = random (Duree_flash_mini, Duree_flash_maxi) ;
  41. Duree_int = random (Duree_int_mini, Duree_int_maxi) ;
  42. digitalWrite (Broche, HIGH) ;
  43. delay (Duree_flash) ;
  44. digitalWrite (Broche, LOW) ;
  45. delay (Duree_int) ;
  46. }
  47. P_repos = random (P_repos_mini, P_repos_maxi) ;
  48. delay (P_repos) ;
  49. }
__________________
Programme « PWM »
 
Programme ATtiny_troisPWM :
  1. // ************************************************************************
  2. // ATtiny_troisPWM.ino
  3. // ************************************************************************
  4. // Envoie un signal PWM de 15% sur broche 3 (PB4), 50% sur broche 5 (PB0)
  5. // et 85% sur broche 6 (PB1).
  6. // La LED sur broche 7 (PB2) est allumee en permanence
  7.  
  8. const byte led1 = 4; // PB4 ou broche 3
  9. const byte led2 = 0; // PB0 ou broche 5
  10. const byte led3 = 1; // PB1 ou broche 6
  11. const byte led4 = 2; // PB2 ou broche 7
  12.  
  13. void setup() {
  14. pinMode(led4, OUTPUT);
  15. // pas d autre declaration avec AnalogWrite
  16. digitalWrite(led4, HIGH); // allumage de LED
  17. // generation des trois PWM de rapport cyclique 15, 50 et 85%
  18. analogWrite(led1, 38); // PWM 15%
  19. analogWrite(led2, 128); // PWM 50%
  20. analogWrite(led3, 217); // PWM 85%
  21. }
  22.  
  23. void loop() {}

Looney_tunes.png

Ressources ANDROÏD – ARDUINO

bottom of page