Formations:Arduino:Initiation:En

From Electrolab
Revision as of 15:51, 4 October 2016 by Clément (Talk | contribs)

Jump to: navigation, search


Contents

Introduction to microcontrollers with the Arduino platform

Arduino, the famous microcontroler board, makes it easy to hack embedded systems that involves sensors, actuators, programs. In this workshop, we'll discover what it can do: input, output, communication. To do so, we'll play with several challenges that an Arduino can easily solve.

This workshop is open to everyone, and is intended as an help for your first steps in the Arduino world.


Info

  • Duration: 3h or more
  • Target audience: any Electrolab member, beginner level in computer programming/electronics/Arduino

Related trainings

  • prerequisite: nothing special, except ability to read & basic computer skills
  • Ideally:
  • Following trainings:
    • My First Arduino Project

Equipment

It is mandatory to bring your own laptop. You must install the Arduino software before the training. Please refer to https://www.arduino.cc/en/Main/Software

Examples and exercices on this page use content from the Arduino starterkit, Electrolab version. This kit is sold 30€, and several kits are also available during the training

Contents :

  • Arduino Nano + USB cable
  • breadboard (400p) and cables male/male et female/female
  • potentiometer and pushbutton (joystick)
  • leds: red, green, yellow, white, blue, RGB and resistor (x8) 330 ohm
  • photoresistor & thermistor + adapted resistor set (2x1k, 2x10k, 2x100k)
  • micro-servomotor, buzzer

Warning: the Arduino nano board that we use require a special device driver ! These are dirtycheap clones made in China.

IDE (software) installation

(maybe move this section some place else?)

See https://www.google.com/?q=ch340+driver to install the mandatory specific device driver without which our kits wont work

Additionnal info

To buy equipment:

  • the Electrolab sells a few components & modules, additionnaly to the starterkit
  • many many shops sell Arduino stuff: Sparkfun, Adafruit Industries, Lextronic, Snootlab, etc

About Arduino

About programming

About electronics

Content of the training

This is designed to be a training at the Electrolab. One can probably follow along without coming to the actual training on site... but this page needs more work before this is a good option. Slides from the training will be published here later on.

Introduction

This training intends to help you discover microcontrollers and how to use them, by using the Arduino platform. No special knowledge is required for this training: we'll see along everything we need. Of course, if you want to know more on the topic of electronics and computer programming, you should check out our trainings on these topics.

Let's see what microcontrolers are, how to use them. This will open the gates to a vast diversity of projects !

Preliminary: notions of electronics and computer programming

In this training we'll use:

  • elecronics related concepts:
    • electricity, voltage/current
    • electronic circuit, schematic & component model
  • computer programming related concepts:
    • what is a computer program? a programming language? How to use this?
    • C language semantics and Arduino specific keywords.
    • workflow associated with computer programming: design, writing your program, compiling, testing & bug tracking, ...

We have trainings on these topics.

In any case, no need to be an expert to follow along the Arduino training: do not hesitate to ask questions along the way, including (most encouraged) to your neighbours.

Microcontrollers

To learn more, here's the manufacturer webpage of the central chip that we will use: http://www.atmel.com/devices/atmega328p.aspx

The main technical reference document is its datasheet. This is a long but very interesting read, that you should at least check out quickly: http://www.atmel.com/Images/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_datasheet.pdf

There are course material pages on there: https://fr.wikiversity.org/wiki/Micro_contr%C3%B4leurs_AVR


What is a microcontroller?

A microcontroller is a type of chip that is widespread. It can be seen as a small computer that is all integrated on one silicon chip: processor (CPU), memory (RAM & flash), various input/output managers, various peripherals, ... all in one single tiny chip. This thing is thus capable of interacting closely with the real world: measure physical values with various sensors, and act upon the world by driving actuators. Inbetween sensing and actuating (input and output), the central processor makes "decisions": it executes the program that has been written by you or someone else, and thus follows strictly the behavior that has been described.

This is a powerful thing: by just writing a different program, you can completely change the behavior of the system. It is also super flexible, because your program can be arbitrarily complex, and give an also arbitrarily complex behavior to the system.

TODO: picture of the chip on the board: systemic view, with inputs, arrows, CPU+software, arrows, outputs

What is a microprocessor?

We also use the acronym: CPU, central processing unit. That's the thing at the heart of a computer, that executes the instructions corresponding to a program. These instructions are very simple:

  • add the value 42 to the memory location #3
  • if memory location #3 is zero, go execute instruction two locations lower in program memory.
  • otherwise, execute the one one location lower in program memory.

It is not easy to give computers instructions at such a low level of absstraction (eg, assembly leve), because one has to know exactly what the CPU at hand can or cannot do, and how. Most importantly, it is impossible to give complex orders (with a high level of abstraction), like "display an image" or "compute the average value of a group of values". The natural tendency is to use programming language with more and more evolved, abstract, complex instructions (high level languages), that make the programmer's job easier.


Physical implementation of a CPU is a fascinating topic: it's where the fronteer between hardware and software is blurry, and where the magic happens : let's keep it for the "introduction to digital electronics" training...

What is binary and number of bits?

CPU can handle only 0 and 1: these a digital circuits. To manipulate "real" number, we use base 2, which considers 1 and 0 as digits to represent any number. For example, the number 6 that you well know (formally, can be written as 6*10^0), can also be written as 2+4, or, with base 2: 1*2^2 + 1*2^1 + 0*2^0, or again 110 (base two). These digits that can be 0 or 1 are called bits, or binary digits.

One major parameter of CPU design is the size of numbers it can natively handle: it depends on how many digits (bits) it can handle at once for a given number. For example, the microcontroler we use in these Arduino has an 8bits CPU: internally, it uses 8 digits numbers, each digit being either 0 or 1.

So, that should mean the largest number it can handle is 1*2^7 + 1*2^6 + 1*2^5 + 1*2^4 + 1*2^3 + 1*2^2 + 1*2^1 + 1*2^0 = 255. Quite small!

You may ask: what's up with negative numbers, decimal (eg 1.27) numbers, etc... there are ways to do this, but it isnt easy for a small CPU like the one in the Arduino's microcontroller.


See:

What are they useful for? Where?

Many things: interface sensors & actuators of any kind, and decide behavior through writing a programm makes it possible to create sooo many cool things. For example, a washing machine, a modern car, an elevator, ... many, most if not all everyday objects rely on a microcontroller to function as expected. It could be seen as the brain ot said object.

TODO: picture of a simple system: input, output, software, for an everyday object.

For example {any closed loop system, or finite state machine based system, that audience can relate to: washing machine, elevator, ...?)


How to use it?

  • system design: first, think and make explicit what it is that you're trying to do. What input will you use, and how? Which outputs do you expect, and when? What is the overal expected behavior? What are the missions/goals?
  • hardware design: once this is all clear, design & create the hardware, create the schematic with selected sensors & actuators. It may make sense to separate clearly different modules, and perform hierarchical design: first learn how to get values from this sensor, then, tackle all issues specifically related to that motor, before trying to do everything at once.
  • software design: once your hardware is ready, you can work on software: here again, it probably makes sense to start with separate modules: divide to conquer applies here. Try out bits of software, think about your overall design before writing code.
  • Tests, bug tracking & modifications to the design: nothing ever works the first time...

The Arduino platform & world

Arduino has been design for students in design and artists, which means non specialists in electronics, computer science and embedded systems, to allow them to design and hack things that require a microcontroller. This means that "easy to get started with" is at the first position in the requirement list for Arduino. As we shall soon see, this is quite a success!

Teaching support: create a tool that is easy to use and allows student to do stuff. Wiring is almost as important as Arduino (boards). Is based on free software, and is itself free, too (as in free speech, not free beer: you still have to buy the boards)

What is Arduino ?

Compared to the many boards & platforms that existed before Arduino, several aspects make it 100% more awesome:

  • Opensource: it relies on existing opensource projects, and everything that has been added is also published under free licenses. This has the usual advantages of free software.
  • Cheap: by design, the board had to cost not more than one meal. Being affordable allows people to actually get one and play with it without the fear to destroy it. It began at around 20€ per board, which was 5x cheaper than similar platforms. Now, dirtycheap clones cost few € each.
  • Not a toy or just a teaching contraption: they designed an easy to use and intuitive interface, shortcuts in the programming language, and a robust electronic board. BUT all this relies on "real" tools that professionnals use everyday, making them easier to use. This allows anyone to check what's under the hood after the first few steps, and get your hands dirty if you need or want to.

All this worked well beyond initial plans, and a growing number of people started using Arduino, contribution upgrades, documenting projects, additionnal modules and features... today, the community is extremely active and powerful. There are an incredible number of sensors, actuators, code and project example out there for anyone to learn from and use in whatever project they like, making a wide range of project much, much easier to achieve.

Anatomy of an Arduino electronic board

Arduino nano board: picture, feature sheet, etc...

In this training, we'll use an all integrated board: the Arduino Nano


picture of a Nano


pinout of a Arduino Nano

Features of our Arduino board

Added to the CPU (that executes the software that we write) and the memory (flash, to store the data even when the power is out, and RAM for the value we're working on), the microcontroler on the Arduino board knows various different tricks:

  • A bit more than ten inputs that we call "digital": the mcu can "see" the presence or absence of a voltage, at defined levels. Our program is able to read the value of the voltage on a pin that is configured as an input, and we can use the value read in our program. We use the term "high" and "low" level, for a voltage of 0v or 5v between that pin and the GND pin of the microcontroller.
  • These pins can also be configured as outputs: here, it is the CPU (and thus, our program) that forces the voltage level, either high (5v) or low (0v). Warning: there is a power limit on what each pin and the whole mcu can provide! Each pin can source (eg, it flows out of the chip) or sink (eg it flows in the chip) 20mA, not more. It is the power level required to light an average LED... moving an electric bike may require 1000 times more power: the mcu cannot do this without additionnal circuitry.
  • Analog voltage inputs (between 0v and 5v): the mcu we use has a very useful peripheral: an Analog Digital Converter. It can convert an analog voltage (here, between 0 and 5v) present on a specific input pin (6 of them on our board) into a value between 0 and 1023. Why this range? It uses 10 bits numbers. So for exemple, if there is a voltage of 2.5v on an analog input pin, the ADC will read a value of 512 (1023*2.5v/5v = 512).
  • For various reasons, there is no easy way to generate an output other than 0v or 5v... dont worry, we'll see how to achieve this with different tricks later !

The mcu we use also contains all the required hardware to communicate with a computer. It also has lots of other peripherals and things more sophisticated, that can be learnt about later. Please read the datasheet, that is an exhaustive source of information on the chip's features.

Note: it has enough RAM (to store variables) and flash memory (to store our program) for most of the applications we can work on.

Use the software tool

We use the Arduino IDE to write our program, compile (eg transform from human readable to machine usable) it and transfer it to the Arduino board memory through the USB connexion.


  • menus: chose board & port, access the example projects
  • buttons: upload, launch terminal/serial monitor

TODO: lots of pictures

Software install

Installation/verification of the IDE and driver. Note: this should be on anoter page..? just refer to the official page?

TODO: pictures de partout.

  • howto install IDE : see official website
  • howto install driver: harder, as it seems that no website is stable enough as a reference...
  • Installation pas à pas du driver



What's in the starterkit?

Let's check out the Arduino Starterkit contents.

TODO: lots of pictures ; maybe link to other pages instead (eg doc of the kit)

  • Breadboard
    • describe how it works
    • explain how to create a circuit
  • component X: TODO

Outputs

Let's get our hands dirty with the output capabilities of the Arduino. The first example ever is to play with a LED.

Turn on and off a LED

"blink" example and basic functions

Our first program is named "Blink", it blinks a LED. It is an example program provided by the Arduino IDE. It can be found in File/Example/Basics.

Once you've opened this project, clic on the "upload" button to compile the code, and transfer the resulting binary into the mcu flash memory. As a result, the LED called "L", that is connected to pin 13 on an Arduino, blinks at a steady pace.

This rather simple test is the traditionnal first step with any new mcu platform: congratulations, you've just made your first step with an Arduino :)


Wiring: There is no need to do any type of wiring: everything that is required is already on the Arduino board we use!

TODO: pictures.

Understanding the schematic: The schematic is very simple: a LED is connected to the D13 pin of the mcu. There is a resistor in serie, to limit the current to an acceptable value. The LED is correctly oriented so that there is current flowing through it when the pin D13 is set at 'HIGH'.

One can check the Nano board schematic to understand, check components values, etc. For example, the resistor is 330 ohm, one can guess that the LED has a threshold value of 2v, so when there's a HIGH value on D13 (eg 5v), there is 3v across the resistor, so a current flowing through it of 3/330 A, which is approximately 10mA: that's alright for a LED that can probably withtand currents up to 50mA, and the mcu that can do 20mA.

TODO: picture schematic arduino output 13 +resistor + LED, current & voltage.

Source code: Let's check the source code:

  • setup() is a function (bloc of instructions) that gets executed when the board powers up. It is useful to do all the setup that we need for our project. Here: explicit that pin 13 shall be an output (output: the MCU drives the state of that pin)
  • loop() is a funciton (bloc of instructions) that gets repetedly executed - as a loop. It contains four lines:
    • we turn the LED on by driving the pin D13 to HIGH
    • we wait for 1000 milliseconds, which is one second
    • we turn the LED off by driving the pin D13 to LOW
    • we wait for 1000 milliseconds, which is one second

TODO: pretty print source code blink

Challenge 1: change blinking speed

Question: how can we change the speed at which the LED blinks?

Not a theory question: try to change the code to have the LED blink at a different speed, and clic the upload button to check if your modification achieves your goal.

Answer: {TODO: shall be hidden/spoiler protected!}

  • by changing the value 1000, we change the wait time after we turn the LED on and off. For example:
    • with the values 200 and 200, the LED blinks 5 times faster
    • with the values 2000 and 2000, the LED blinks 2 times slower
    • with 500 and 1500, the LED blinks at the same speed, but it is turned on for less long

Result:

  • Understanding of a simple program
  • we've immediately done something real with that LED!

Challenge 2: SOS in morse code

Question: how can we create more complex blinking patterns? For example, let's do the famous "SOS" in morse code: ...---... which is three short flashes (code for 'S'), three long (code for 'O') and again three short flashes.

Let's display this on the L LED!

Remember: even on a simple example, a well structured and cleaned up program is much better.


Answers to 2.1
  • there are several different ways of achieving this:
    • copy paste the four lines of code we already know as many times as required, with changed values for the delay() function
    • create our own functions, like "short_flash()" and "long_flash()", or display_S() and display_O()
  • use parameterized code makes sense:
    • having "magic numbers" everywhere we use delay() is problematic: it isnt easy to change these values, and when reading the code, who knows why the value is 1000 or 500?
    • Let's create "variables" :
      • const int period_flash_short = 200;
      • const int period_flash_long = 1000;
    • We can use these everywhere as required, and then play with the values more easily.
Answer to 2.1 with copy paste

void setup() {

 pinMode(13, OUTPUT);

} void loop() {

 /* display 's' : three short flashes */
 digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
 delay(200);              // wait for 200ms
 digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
 delay(200);              // wait for 200ms
 digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
 delay(200);              // wait for 200ms
 digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
 delay(200);              // wait for 200ms
 digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
 delay(200);              // wait for 200ms
 digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
 delay(200);              // wait for 200ms
 /* display 'o' : three long flashes */
 digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
 delay(1000);              // wait for a second
 digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
 delay(1000);              // wait for a second
 digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
 delay(1000);              // wait for a second
 digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
 delay(1000);              // wait for a second
 digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
 delay(1000);              // wait for a second
 digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
 delay(1000);              // wait for a second
 /* display 's' : three short flashes */
 digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
 delay(200);              // wait for 200ms
 digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
 delay(200);              // wait for 200ms
 digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
 delay(200);              // wait for 200ms
 digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
 delay(200);              // wait for 200ms
 digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
 delay(200);              // wait for 200ms
 digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
 delay(200);              // wait for 200ms

}

Answer to 2.1 with functions and parameters

const int period_flash_short = 200; const int period_flash_long = 1000;

/* short flash: period_flash_short ms on, period_flash_short ms off */ int short_flash(void) {

 digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
 delay(period_flash_short);              // wait for 200ms
 digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
 delay(period_flash_short);              // wait for 200ms

} /* short flash: 1s on, 1s off */ int long_flash(void) {

 digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
 delay(period_flash_long);              // wait for a second
 digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
 delay(period_flash_long);              // wait for a second

} /* display 's' : three short flashes */ void display_S(void) {

short_flash();
short_flash();
short_flash();

} /* display 'o' : three long flashes */ void display_O(void) {

long_flash();
long_flash();
long_flash();

}

void setup() {

 pinMode(13, OUTPUT);

} void loop() {

 display_S();
 display_O();
 display_S();

}


Bonus Question 2.2

How can we change the morse code displaying speed?

Answers to 2.2

Another obvious reason why parameterized code is better than "hardcoded" values. const int period_flash_base = 200; const int period_flash_short = 1; const int period_flash_long = 5;

/* short flash: period_flash_short ms on, period_flash_short ms off */ int short_flash(void) {

 digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
 delay(period_flash_short*period_flash_base);              // wait for 200ms
 digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
 delay(period_flash_short*period_flash_base);              // wait for 200ms

} /* short flash: 1s on, 1s off */ int long_flash(void) {

 digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
 delay(period_flash_long*period_flash_base);              // wait for a second
 digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
 delay(period_flash_long*period_flash_base);              // wait for a second

} /* display 's' : three short flashes */ void display_S(void) {

short_flash();
short_flash();
short_flash();

} /* display 'o' : three long flashes */ void display_O(void) {

long_flash();
long_flash();
long_flash();

}

void setup() {

 pinMode(13, OUTPUT);

} void loop() {

 display_S();
 display_O();
 display_S();

}


Bonus Question 2.3

How to change the message sent?

Answers to 2.3

We could create a function that takes a character as argument, eg "display_morse(char c)" or similar void display_morse(char c) {

 swithc(c) {
   case 's':
    short_flash();
    short_flash();
    short_flash();
    break;
   case 'o':
    long_flash();
    long_flash();
    long_flash();
    break;
   default:
     break;
 }

}

Variable intensity with a LED

Challenge 3: ultra fast blinking

Question: what happens when you blink a led suuuuper fast?

Once again: you can think about it... or directly try it out! Change the value in delay, eg first try delay(100), then maybe delay(10), and why not delay(1)

Answer: because of persistence of vision, one can't distinguish each flash when they happen too fast, and instead we see an average intensity.

Question: find out which blinking speed is the limit above which one cannot see each flash.

Answer: with delay values 10 and 10, eg approximately 50Hz (50 blink a second), it is hard to see each blink. They are impossible to count, at least!

Question: what does it even mean, suuuuper fast, for the microcontroller?

Answer: the central reference clock (that is kind of a metronome) for the central processor unit is at the frequency of 16MHz. Each second, the central CPU gets 16.000.000 ticks, and performs a basic action. Much lower than a modern PC or smartphone (100 times faster, at aroung 2GHz, or 2.000.000.000 ticks per second)... but blinking 50 times a second is fast for a human eye, but not really for a microcontroller.


Défi 4 : jouer avec les délais

Question: il se passe quoi quand on a des valeurs de delay différentes ?

Allez-y, tentez par exemple delay(200) et delay(800), et inversement delay(800) et delay(200). Dit autrement: allumé 200ms puis éteint 800ms, et inversement, éteint 200ms puis allumé 800ms. Testez d'autres valeurs, par exemple: 1/9, 3/7, 5/5, 7/3, 9/1...

Réponse: notion de rapport cyclique (c'est à dire rapport entre durée allumé et durée éteint) et fréquence (c'est à dire le nombre de fois par seconde que la LED s'allume/s'éteint). Cela permet de modifier la valeur moyenne perçue à l’œil. Même si le microcontrôleur n'a pas de moyen direct de générer une valeur analogique (c'est à dire, pas seulement "marche" ou "arrêt", mais aussi des valeurs intermédiaires), avec l'astuce de la PWM, on peut obtenir un résultat équivalent.

Notion de PWM et sortie analogique

Ce que l'on vient de découvrir s'appelle PWM, pour Pulse Width Modulation, ou MLI en français, pour Modulation de Largeur d'Impulsion.

C'est une technique qui permet simuler une sortie analogique (c'est à dire valeur quelconque entre 0v ou 5v, au lieu d'exclusivement 0v ou 5v pour une valeur digitale) à partir de quelque chose en tout ou rien. On parle aussi de hachage, ou découpage. C'est une technique très, très fréquente en électronique, parce qu'il est plus facile (voir uniquement possible) de faire du tout ou rien, alors que souvent on veut des variations continues.

TODO: pictures pour l'explication PWM/rapport cyclique, etc

TODO: pictures Schéma U/T pour visualiser la forme d'onde générée, et la moyenne.

Note : il existe d'autres techniques pour avoir des valeurs variables à partir de tout ou rien, mais la PWM est souvent la plus pratique et simple. Pour les curieux, autres techniques: réseau R-2R, transistor en régime linéaire, DAC intégrés (différentes technos), ... TODO: liens wikipedia voire montages & composants pertinents...

Défi 5 : générer une sortie analogique à partir de 0v et 5v

C'est tellement pratique de pouvoir générer une tension arbitraire entre 0v et 5v, qu'on aurait bien envie d'avoir une fonction toute fait qui le gère. Ca tombe bien, Arduino a une fonction toute prête pour cela: analogWrite (voir la page de référence).


Histoire de mieux comprendre ce qu'il se passe, on peut tenter d'en écrire nous même une version. On va créer une fonction my_analogWrite(int pin, int value):

  • pin étant une valeur de pin (qui devra avoir été configurée en sortie dans le setup() bien évidemment).
  • value étant une valeur entre 0 et 255, donnant l'intensité

Solution primitive: on pourrait utiliser quelque chose du genre de:

  • digitalWrite(pin, HIGH); delay(value);digitalWrite(pin, LOW); delay(255-value);

Probleme: 255 millisecondes, ca fait un peu beaucoup, comme période: seulement 4 clignotements par seconde... comment faire pour en avoir au moins 50?

Réponse: on peut utiliser la fonction DelayMicroseconds au lieu de delay tout court:

  • digitalWrite(pin, HIGH); delayMicroseconds(100*value);digitalWrite(pin, LOW); delayMicroseconds(100*(255-value));

TODO: Code en pretty print


Note: on peut aussi aller regarder le code source de la librairie analogWrite elle-meme. On le trouve dans les fichiers des dossiers ou l'IDE est installé, et il est sur github : le fichier source est ici.

Ouille ouille ouille, on voit bien que le code est un peu plus compliqué que le notre ! Plusieurs raisons à cela:

  • il est générique, et marche sur plusieurs types de cartes Arduino (il
  • il utilise des fonctionnalités qu'on ne connait pas encore: en matériel, le microcontrôleur sait générer des PWM "tout seul" grâce à un bout de matériel spécialement prévu pour. Pour les curieux, tout cela est expliqué dans la doc technique du composant, à la page 111/660 dans le chapitre sur le périphérique 'timer' : c'est un peu obscur... mais ca se décrypte, avec (beaucoup de) motivation. Une fois configuré, le CPU n'a pas à intervenir pour que la PWM soit générée. Ultra pratique pour pouvoir faire autre chose en parallèle...

Exemple Fade et fonction analogWrite

Le code se trouve dans le menu Exemple/Basics/Fade.

Le schéma: est très similaire à celui de Blink... mais il faut relier la LED à une pin marquée ~ pour pouvoir utiliser la fonction analogWrite, dépendante de fonctionnalité spéciales du matériel. On va utiliser la pin 9, par exemple. Attention à ne pas oublier de mettre une résistance en série pour limiter le courant !

TODO: pretty print schéma/montage breadboard & pic

Le code source:Regardons maintenant le code source:

  • la fonction setup(), exécutée au démarrage de la carte, permet de faire tous les paramétrages requis. Ici, on indique que la pin 9 est une sortie
  • la fonction loop() est ensuite exécutée en boucle. Elle contient plusieurs choses:
    • application de la valeur actuelle de luminosité (brightness) sur la led
    • mise à jour de la luminosité, par un petit incrément/décrément (fadeAmount peut être positif... ou négatif!)
    • mise à jour de l'incrément/décrément: on change son signe pour varier alternativement de maximum à minimum et inversement.
    • un petit délai pour voir les variations


TODO: pretty print source code Fade

Défi 6 : fade & RGB

Faisons des modifications à fade: utiliser une led RGB, c'est à dire gérer plusieurs sorties à la fois! On peut ensuite générer des séquences aussi variées qu'on veut !

Micro projet: feu tricolore

Avec tout ce qu'on vient de voir, on est en mesure de concevoir et réaliser un feu tricolore. On va utiliser trois leds et les résistances associées: une verte, une jaune (ou orange) et une rouge. Les résistances seront choisies à une valeur appropriée pour limiter le courant.

Remarque: on peut utiliser le montage tout fait "feux de circulation lab". TODO: créer page & lien.

Pour commencer, on peut faire un feu simple: au vert pendant 3 secondes, orange pendant 1 seconde, et rouge pendant 3 secondes, puis on recommence.

TODO: feu trivial: pic montage

TODO: feu trivial: code source "solution"

On peut ensuite imaginer plusieurs évolutions/améliorations: ajout d'un témoin vert/rouge de passage piéton, gestion d'une intersection (c'est à dire, deux jeux voire plus de trois leds)... et assez rapidement, on va avoir envie de faire d'autres choses, comme par exemple avoir un bouton de demande passage au vert pour les piétons, voire un capteur de présence de véhicule... on peut le faire, mais il nous faut apprendre comment ca marche d'avoir des entrées sur le microcôntroleur !

Lire l'état d'entrées

Pour réellement faire plein de choses intéressantes avec un microcontrôleur, on a besoin de savoir mesurer des trucs dans le monde réel, pour fournir des informations à notre application. Dans toute cette section, nous allons utiliser le joystick contenu dans le kit de découverte Arduino.

Bouton et entrée digitale (au choix, 0v ou 5v)

Commençons par la plus simple des entrées: un interrupteur basique. Il y en a un par exemple dans le Joystick du kit: lorsqu'on appuie dessus, on entend distinctement un "clic".


Exemple "Button"

Le code se trouve dans le menu Fichier/Examples/Digital.

Le montage: TODO description du montage: gnd, SW, résistance pulldown.

TODO picture: fritzing schéma

Comprendre le schéma: rôle de la pulldown... et pullup.

TODO picture: role de pulldown/pullup/tensions appuyé/non appuyé

Le code:

  • la fonction setup(), exécutée au démarrage de la carte, permet de faire tous les paramétrages requis: on indique que la pin 13 est une sortie (pour piloter la led) et que la pin 2 est une entrée.
  • on va utiliser une variable (buttonState) pour mémoriser l'état du bouton : on la déclare.
  • la fonction loop() est ensuite exécutée en boucle. Elle contient plusieurs choses:
    • lecture de l'état de la pin 2 grâce à la fonction digitalRead
    • en fonction de l'état de la pin 2 enregistré dans la variable buttonState: éteindre ou allumer la led L.

Défi 1: changer le fonctionnement

Qui a dit que le bouton devait faire X plutot qu'autre chose? Nous, avec le code! Comment changer vers un mode toggle (eg appui veut dire changer d'état) ?

TODO: détailler l'énoncé du défi.

Réponse: structure du code

  • Lire l'entrée
  • prendre des décisions
  • appliquer les sorties.

Désolé pour la mise en page (en attente de pretty print wiki) :

int buttonState = HIGH; int buttonState_old = HIGH; int ledState = HIGH;

void setup() {

pinMode(button_pin, INPUT_PULLUP);
pinMode(led_pin, OUTPUT);

}

void loop() {

 buttonState = digitalRead(buttonState);  // on lit l'entrée
 if((buttonState == LOW) && (buttonState_old == HIGH)) { //appui bouton?
   if(ledState == HIGH) {  //la led était allumée, on l'éteint
     digitalWrite(led_pin, LOW);
     ledState = LOW;
   }
   else {
     digitalWrite(led_pin, HIGH);
     ledState = HIGH;
   }
 }
 delay(100); // permet de faire un debounce: on verra plus tard ce que ca veut dire.

}

Défi 2: menu simple par durée d'appui

Comment on peut faire "sentir" à la carte un peu plus que juste "marche/arret" ? Par exemple, en différenciant les appuis longs et appuis courts.

Exemple d'interface : différencier les appuis longs ou courts permet d'augmenter ou de diminuer la luminosité d'une led.

En pratique: analogWrite/Fade, si appui <1s, réduire intensité de 20%, si appui >1s, augmenter de 20% (entre 0 et 100%)


Défi 3 : menu simple par comptage d'impulsions

Comment on peut faire "sentir" à la carte un peu plus que juste "marche/arret" ? Par exemple, en comptant le nombre de fois ou on appuie/détecter le doubleclic.

Exemple d'interface : compter le nombre d'appuis successifs/détecter doubleclic.

  • toggle avec deux leds? +/- vitesse? analogWrite/Fade?

Notion de rebond

Meta: Exemple Input->Serial et rebonds?, avec le port serie, fait à moitié un debounce... mais à vérifier. Sinon, pratique pour voir le rebond!

Meta: comment amener le rebond? Defi 3: compter le nombre... et ca fail?

Note: en utilisant INPUT_PULLUP dans pinMode, on peut se passer de la résistance. En effet, le microcontroleur contient des résistances de pull-up, qu'on peut activer en logiciel. Voir par exemple l'exemple InputPullupSerial.

Meta: est-ce qu'on voudrait pas introduire millis() ici? Permet de faire des trucs archi cool genre un fréquencemetre, un pseudo scheduler, ...

Attention, piège du bounce (ou rebond, en francais). Lorsqu'on appuie sur le bouton, la lamelle de metal qui fait contact rebondit plusieurs fois (pendant 1/100e de seconde) avant de se stabiliser. Cela n'a pas d'importance si on se sert de cette information pour allumer ou éteindre la led, parce que l'oeil ne s'en rend pas compte. Par contre, lorsqu'on compte les changements d'état, cela risque de poser probleme! En effet, le microcontroleur, qui est rapide (16 millions d'opérations par seconde!) a amplement le temps d'observer et de compter chacun de ces rebonds, faussant complètement notre application.


La mesure preventive correspondante est appellee "debouncing" ou anti-rebonds. C'est quoi le debouncing? Il s'agit de s'assurer que la transition vue par le microcontroleur est "stable", c'est à dire qu'on va tenter d'éliminer les transitions dues aux rebonds.

Comment faire? Il y a plusieurs techniques. Par exemple, on peut ne prendre en compte les transitions seulement après une période choisie de stabilité: on regarde toutes les 50ms l'état de l'entrée, et seulement lorsque trois mesures successives donnent la meme valeur, on prend en compte cette nouvelle valeur.


TODO: ajouter picture pour comprendre le debounce.


Voir par exemple: https://www.arduino.cc/en/Tutorial/StateChangeDetection


Conclusion: meme si tout cela reste encore rudimentaire, on a vu une chaine complete:

  • Entrée: appui(s) bouton
  • Traitement: selon la logique que l'on décrit avec notre programme, le microcontroleur va avoir un comportement different
  • Sortie: allumer ou éteindre une LED

Voyons maintenant des entrées/sorties encore plus cool ! => OK! On peut mesurer des trucs mieux que juste marche/arret.

Potentiomètre et entrée analogique (mesure entre 0v et 5v)

C'est bien les boutons, mais pas assez: potard. Sur le joy, position x et position y.

Exemple "AnalogInput"

Nous allons utiliser le programme d'exemple qui s'appelle "AnalogInput", il fait clignoter une LED avec une vitesse réglable par potentiomètre. Le fichier du projet se trouve dans le menu Fichiers/Exemples/Analog.

Le montage: TODO frizting.

Comprendre le schéma: pont diviseur de tension... mesure de résistance par mesure de tension. On ne sait QUE mesurer des tensions!

Le code source:

  • la fonction setup(), exécutée au démarrage de la carte, permet de faire tous les paramétrages requis:
    • la pin 13 (ledPin) est une sortie.
    • on ne déclare pas d'entrée Analog!
  • on se fait des variables: sensorValue.
  • la fonction loop() est ensuite exécutée en boucle. Elle contient XXX instructions:
    • mesurer la valeur de la tension sur la pin A0 avec analogRead TODO lien ref
    • utiliser la valeur lue comme paramètre de la fonction delay dans l'exemple Blink

TODO: pretty print source code AnalogInput

Défi : potard vers fade

TODO: texte.

Encore une fois: c'est à notre programme de decider ce que veut dire "bouger tel bouton" ou "déplacer le potentiometre".

Ici, relier à Fade.

  • Relation linéaire

Réponse: bla bla code.

Défi : potard roulette russe

TODO: texte.

Encore une fois: c'est à notre programme de decider ce que veut dire "bouger tel bouton" ou "déplacer le potentiometre".

  • Relation seuil... et notion d'hysteresis.

Réponse: bla bla code.

Microprojets: retour aux vieux codes, coffre fort

Note: toujours bien sauvegarder et ranger chacun de nos codes... la preuve, ils vont servir à nouveau ici!

Revisitons nos anciens codes:

  • reprendre le morse, et changer la vitesse de defilement (difficile/nécessite un code bien structure).
  • défi: piloter la RGB de facon marrante (par exemple, intensité d'éclairage, ou balance de couleur, ou vitesse de defilement de toutes les couleurs...).
  • défi: simuler le vent/led comme flame (nécessite d'aller chercher random dans la reference)
  • menu avec bouton, joystick... à préciser :P

TODO: détailler les énoncés, donner les réponses code et montage

Communication avec le PC

Maintenant qu'on sait piloter des bidules et en mesurer d'autres, on aurait bien envie de pouvoir communiquer avec l'ordinateur. Ca tombe bien, c'est possible (c'est d'ailleurs ce qu'on fait quand on charge notre programme sur la carte!), avec le périphérique UART, et la librairie "Serial". Voyons comment tout cela fonctionne...

Communication Arduino -> PC

Permet de remonter des informations, des mesures...

Exemple "AnalogInOutSerial"

Nous allons utiliser le programme d'exemple qui s'appelle "AnalogInOutSerial", il fait XXXX et YYYY. Le fichier du projet se trouve dans le menu Fichiers/Exemples/Analog.

Le montage: TODO frizting.

Comprendre le schéma/installation: TODO rien de spécial..? notions (baudrate, moniteur série) à la place?

Le code source:

  • la fonction setup(), exécutée au démarrage de la carte, permet de faire tous les paramétrages requis:
    • on initialise le module Serial avec la valeur de baudrate (vitesse de comm') à 9600.
    • on ne déclare pas d'entrée Analog!
    • D13 est une sortie.
  • on se fait des variables: sensorValue et outputValue
  • la fonction loop() est ensuite exécutée en boucle. Elle contient XXX instructions:
    • mesurer la valeur de la tension sur la pin A0 avec analogRead TODO lien ref
    • map: pour changer la dynamique. Indispensable ici!
    • Serial.print de chaine fixe.
    • Serial.print de variable.


TODO: pretty print source code AnalogInSerialOut

Défi  : afficher autre chose que la valeur brute?

  • Par exemple, un coffre fort? Eg si potards à la bonne valeur (voire, une suite de positions), afficher un mot de passe sur port série. Ou roulette russe avec des hints
  • Par exemple, du "filtrage": lorsqu'on regarde les valeurs defiler, on constate que ce n'est pas très précis/stable.

Défi : serial et debug

  • Exemple: se servir de la sortie UART pour "debugger": reprendre l'exemple du bouton, et tenter de caractériser le phénomène de rebond/ajuster notre debouncing. Remarque: on pourrait aussi plus proprement utiliser un oscilloscope...

Communication PC -> Arduino

Envoyer des commandes et des infos à l'Arduino depuis le PC!

Exemple "SerialInAction"

Nous allons utiliser le programme d'exemple fait sur mesure SerialInAction (TODO: nommer mieux), il fait XXXX et YYYY. Le fichier du projet se trouve XXX

Le montage: TODO frizting.

Comprendre le schéma/installation: TODO rien de spécial/nouveau...? voire rien du tout: L/D13

Le code source:

  • la fonction setup(), exécutée au démarrage de la carte, permet de faire tous les paramétrages requis:
    • on initialise le module Serial avec la valeur de baudrate (vitesse de comm') à 9600.
    • D13 est une sortie.
  • la fonction loop() est ensuite exécutée en boucle. Elle contient XXX instructions:
    • vérification si données dispo avec fonction TODO ref
    • switch TODO ref pour choisir l'action selon le caractere recu.


TODO: pretty print source code custom exemple:

TODO: header comment byte inByte;

void setup() {

 Serial.begin(9600);
 pinMode(13, OUTPUT);

}

void loop() {

 if(Serial.available()>0) {
   inByte = Serial.read();
   switch(inByte) {
     case 'a':
       digitalWrite(13, HIGH);
       break;
     case 'e':
       digitalWrite(13, LOW);
       break;
   }
 }

}

Défi : piloter plusieurs leds

TODO texte et redécoupage.

  • exemple: pilotage RGB

Défi : piloter Fade

TODO texte et redécoupage.

  • exemple: valeurs/paramètres de fade
  • exemple: clignotements différents, eg trig de séquences

Défi : set de valeurs..?

  • exemple: pilotage de notre feu tricolore, voire envoi de commandes spéciales (modifier la durée de tel ou tel feu, changement de mode de fonctionnement...)
  • exemple de parsing de chaine..? probablement trop compliqué par contre on peut faire +/-/set comme exemple bras robot!

Microprojets: XXX

Terminal morse (avec potard pour vitesse) Autre chose de plus phunky?

backdoor paramétrage central intersection

Pour aller plus loin

TODO texte... On sait maintenant gérer des entrées, des sorties, communiquer avec le PC... mais on a que des leds, des boutons et des potards. Heureusement, il y a plein d'autres capteurs/actionneurs plus funky avec lesquels on peut interagir.

Il y a plein de types d'actionneurs différents, on va en regarder seulement deux très simples à mettre en oeuvre: petit buzzer et petit moteur de modélisme. Souvent, piloter ces sorties est plus complexe que simplement sortie MARCHE ou ARRET ; heureusement, il y a plein de librairies (eg, de bouts de code tout faits) à la rescousse pour nous!

On fait le tour de ceux dans le kit découverte... et il en restera 100 fois plus à découvrir ;)

Capteurs de température et de lumière

TODO: meme structure que séquence: exemple de code, montage, compréhension, défis.

Jouer avec pont diviseur de tension, et voir que peu importe ce qui fait la tension, coté code, c'est kifkif bourricot!

Peut importe comment le capteur fonctionne physiquement, l'arduino ne sait que mesurer des tensions ou voir l'état (MARCHE/ARRET) d'une de ses pattes. Bon, elle sait aussi communiquer avec un PC - ou un autre microcontroleur. Ce qui peut etre le cas avec un capteur sophistiqué (eg, il inclut un petit microcontroleur, et renvoit directement des valeurs numériques).

Il y a plusieurs capteurs qui se comportment comme des resistances variables: pour les capteurs de lumiere et de temperature qu'on utilize, c'est le cas. On va donc pouvoir/devoir faire un "faux" potentiometre (on dit pont diviseur de tension, car c'est un montage/une forme/une topologie ultra classique), qui va permettre mesurer la variation de résistance.

IMAGE: vue schématique d'un potentiometre... pont diviseur de tension, fonctionnement identique si on prend notre capteur et une résistance fixe. IMAGE: calcul de la relation d'un pont diviseur de tension: loi d'ohm, loi des mailles.


Note: choix de la résistance dans pont div selon capteur, et calibration avec serial monitor.

Comment on choisit la résistance à coté? ca va marcher avec différentes valeurs... plus ou moins bien. La valeur optimale est la "moyenne log entre valeur min et max de la résistance variable", parce que cela permet d'avoir la plus grande dynamique. C'est à dire: il faut prendre une valeur entre le max et le min de résistance pour avoir la plus grande plage de variation de la tension mesurée. Par exemple, si le capteur change de 100 à 10000 ohm selon qu'il a beaucoup ou très peu (de lumière/de chaleur), on veut mettre une résistance de 1000 ohms.

Remarque: il faut faire attention aussi au courant consommé : ici, 1100 ohms au minimum sur l'alimentation 5v, ca reste OK, car le courant débité sera de 5V/1100ohm = 0.0045A, inférieur à la limite de 0.02A

Exemple : capteur de lumiere

  • schema: pont diviseur de tension. Expérimentation/Serial pour trouver la valeur optimale de résistance, ou bien datasheet...
  • code example, applis marrantes: tous les exemples précédents avec potard marchent ici sans modif ou presque.

Exemple : capteur de température

  • schema: pont diviseur de tension. Expérimentation/Serial pour trouver la valeur optimale de résistance, ou bien datasheet...
  • code example, applis marrantes: tous les exemples précédents avec potard marchent ici sans modif ou presque.


Buzzer et sons

TODO: meme structure que séquence: exemple de code, montage, compréhension, défis.

Exemple : cri de la victoire

Code exemple de tone

Défi : morse en audio

On pourrait avoir le terminal Morse en audio plutot que sur la led.

Défi : theremine

On veut faire un synthétiseur/thérémine avec le joystick/capteur de lumiere.

Microservomoteur et mouvement

TODO: meme structure que séquence: exemple de code, montage, compréhension, défis.


Exemple: swipe

analyse, comme d'hab.

Exemple: knob

analyse, comme d'hab... est-ce vraiment nécessaire? Sinon seulement "voir aussi" dans swipe.

Défi : trappe aération serre

capteur de température et ouverture trappe ventilation serre, hysteresis, etc.

Microprojet: poubelle intelligente

capteur de lumière/capteur de proximité => poulie, servomoteur

Microprojet: bras robot

pilotage par potards et par serial port du kit bras robot 4 axes.

Conclusion

Cette formation a permis de faire nos premiers pas avec un microcontrôleur, en utilisant Arduino:

  • piloter des sorties (digitales et analogiques),
  • lire l'état d'entrées (digitales et analogiques),
  • communications avec le PC (dans les deux sens)
  • capteurs et actionneurs sympa.

On a réalisé plusieurs défis et micro-projets. Quand on veut faire un projet quelconque de plus grande envergure, on fait comme cela aussi: on commence par examiner chacun des petits bouts, avant d'assembler les pièces du puzzle.

D'ailleurs, quel projet allez vous réaliser maintenant ? Libre à vous de décider ! Les possibilités sont très vastes.

la suite

  • Assister à la formation "mon premier petit projet Arduino". L'idée est justement d'utiliser d'autres modules capteurs/actionneurs pour réaliser un petit projet qui vous intéresse (un robot? un automate pour une serre? un jeu?)

=> quel type de projet voulez vous faire? quels capteurs/actionneurs voudriez vous découvrir?

  • Améliorer votre compréhension des microcontrôleurs, de l'électronique numérique, de l'informatique embarquée, ...

=> Qu'est ce que vous voulez apprendre de plus/approfondir?

  • notes/laissés en exercices:
    • grapher les caractéristiques capteur de température, de lumière.
    • faire marcher le buzzer et le servomoteur SANS appel à la librairie
    • -> probablement que ce sont des séances de TP "découverte de bidule: aujourd'hui le servomoteur".
  • projets:
    • bouilloire d'eau avec asservissement température
    • clignotants vélo+système d'éclairage "simple"
    • ouverture auto de couvercle de poubelle (servomoteur et capteur de lumiere)

retours sur la formation

  • Discutons de la formation: qu'est-ce qui a bien marché? pas bien marché? Que faut il garder, supprimer, ajouter?
  • Appropriez vous le contenu. Sauriez vous animer la formation vous meme? expliquer ce que vous venez d'apprendre à quelqu'un d'autre?

A vous la parole: remplissez la fiche d'évaluation. Rangeons le materiel et la salle pour les suivants!

Fourre tout sur la suite

Quelques notes sur les sujets qu'on peut avoir envie d'aborder...

Dans la série purement SW... Fonctions additionnelles:

  • millis, micros ; structure if(time_current>time_last+time_period)
  • attachinterrupt
  • switch case/FSM
  • asservissement

Autres topics SW:

  • RT OS (eg scheduler, mecanismes usuels)
  • bootloader
  • USB (sur 32u4)
  • lib writing/packaging
  • real debugging (eg debugwire)
  • real toolchain (eg avrstudio, eclipse)

Autres topics HW:

  • fork board