le 09/05/2019
Système embarqué (embedded)
Microcontrôleur ATMEGA 328p de ATMEL
Pré-requis
Cours Arduino
C/C++
Liaison série
But
Coder sur un système embarqué , ARDUINO
https://www.sparkfun.com/datasheets/Components/SMD/ATMega328.pdf
L'arduino Uno est réalisé a partir de l'atmega328p de Atmel. (2 dans le UNO)
On fera de la cross compilation (avr-gcc) sur nos pc.
On utilisera l'interface ide arduino.
sudo apt install arduino
C'est bien du C/C++ , même si on premier abord ça ne parait pas évident.
Le programme principal volontairement encapsulé est :
/hardware/arduino/avr/cores/arduino/main.cpp
#include <Arduino.h>
...
...
int main(void)
{
init();
initVariant();
#if defined(USBCON)
USBDevice.attach();
#endif
setup();
for (;;) {
loop();
if (serialEventRun) serialEventRun();
}
return 0;
}
La maquette du lycée avec 4 boutons poussoirs et un afficheur LCD 2x16 caractères
Ce qu'il faut retenir , c'est que le fonction setup() est effectuée une seule fois au démarrage, ensuite loop() est placé dans la boucle infinie avec le for(;;)
Nous verrons ensuite que les librairies sont bien écrite en C/C++
Le câble USB A (rectangle) d'un coté et B (carré) de l'autre
Une interface simple et claire, écrite en Java, portée sur windows,OsX et Linux.
Simple d'utilisation avec un grand nombre d'exemple pour la prise en mains
La Led branchée sur la broche 13 clignote.
La librairie pour le LCD16x2 proposée.
Dans
croquis/inclure une bibliothèque/ajouter une bibliothèque .ZIP
https://www.olimex.com/Products/Duino/Shields/SHIELD-LCD16x2/open-source-hardware
LCD16x2.h
#ifndef LCD16x2_H
#define LCD16x2_H
#include "Arduino.h"
#define SET_TRIS 0x01
#define SET_LAT 0x02
#define GET_PORT 0x03
#define GET_BUT 0x05
#define GET_ID 0x20
#define GET_FRM 0x21
#define LCD_CLR 0x60
#define LCD_WR 0x61
#define SET_BL 0x62
#define UART_EN 0x10
#define BOARD_ID 0x65
#define ADDRESS 0x30
/**
* @author Stefan Mavrodiev @ OLIMEX LTD <support@olimex.com>
* @version 1.0
* @since 2013-11-03
*/
class LCD16x2{
public:
LCD16x2();
~LCD16x2();
uint8_t getID();
uint8_t getFirmwareVersion();
void uartEnable(bool state);
void pinMode(uint8_t pin, uint8_t direction);
void digitalWrite(uint8_t pin, uint8_t level);
uint8_t digitalRead(uint8_t pin);
uint8_t readButtons();
void lcdSetBlacklight(uint8_t value);
void lcdClear();
void lcdGoToXY(uint8_t x, uint8_t y);
void lcdWrite(char *string);
void lcdWrite(int intVal);
void lcdWrite(float floatVal, uint8_t precision);
const static uint8_t GPIO1 = 1;
const static uint8_t GPIO2 = 2;
const static uint8_t GPIO3 = 3;
const static uint8_t GPIO4 = 4;
const static uint8_t GPIO5 = 5;
const static uint8_t GPIO6 = 6;
const static uint8_t GPIO7 = 7;
const static uint8_t GPIO8 = 8;
const static uint8_t GPIO9 = 9;
private:
uint8_t X;
uint8_t Y;
};
#endif
Code LCD16x2.cpp
/*
* LCD16x2.cpp
*
* Copyright 2013 OLIMEX LTD <support@olimex.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include "LCD16x2.h"
#include <Wire.h>
/**
* Default constructor.
*/
LCD16x2::LCD16x2(){
X = 0;
Y = 1;
}
/**
* Default destructor.
*/
LCD16x2::~LCD16x2(){
}
/**
* Read the id of the shield.
* @return If read value match BOARD_ID(0x65) the method return 1,
* otherwise - 0.
*/
uint8_t LCD16x2::getID(){
uint8_t id = 0;
Wire.beginTransmission(ADDRESS);
Wire.write(GET_ID);
Wire.endTransmission();
Wire.requestFrom((int)ADDRESS, 1);
while(Wire.available() > 0)
id = Wire.read();
return id;
}
void LCD16x2::lcdSetBlacklight(uint8_t value){
Wire.beginTransmission(ADDRESS);
Wire.write(SET_BL);
Wire.write(value);
Wire.endTransmission();
}
void LCD16x2::uartEnable(bool state){
uint8_t en;
if(state == true)
en = 0x01;
else
en = 0x00;
Wire.beginTransmission(ADDRESS);
Wire.write(UART_EN);
Wire.write(en);
Wire.endTransmission();
}
uint8_t LCD16x2::getFirmwareVersion(){
uint8_t firm = 0;
Wire.beginTransmission(ADDRESS);
Wire.write(GET_FRM);
Wire.endTransmission();
Wire.requestFrom((int)ADDRESS, 1);
while(Wire.available() > 0)
firm = Wire.read();
return firm;
}
/**
* Set direction of GPIO.
* @param pin The pin number according to schematic: GPIO1, GPIO2, etc...
* @param direction The direction of the GPIO: OUTPUT or INPUT.
*/
void LCD16x2::pinMode(uint8_t pin, uint8_t direction){
Wire.beginTransmission(ADDRESS);
Wire.write(SET_TRIS);
Wire.write(pin);
Wire.write(!direction);
Wire.endTransmission();
}
/**
* If pin is set as output this method define the level of the GPIO.
* If pin is input - it enables internal pull-up resistor (only available
* for PORTB pins).
* @param pin The number of the desired GPIO: GPIO1, GPIO2, etc...
* @param level The output level: HIGH or LOW
*/
void LCD16x2::digitalWrite(uint8_t pin, uint8_t level){
Wire.beginTransmission(ADDRESS);
Wire.write(SET_LAT);
Wire.write(pin);
Wire.write(level);
Wire.endTransmission();
}
/**
* Read the state of individual GPIO, if configured as input.
* @param pin The number of the GPIO: GPIO1, GPIO2, etc...
* @return If input level is high - 1, else - 0.
*/
uint8_t LCD16x2::digitalRead(uint8_t pin){
uint8_t port;
Wire.beginTransmission(ADDRESS);
Wire.write(GET_PORT);
Wire.write(pin);
Wire.endTransmission();
Wire.requestFrom((int)ADDRESS, 1);
while(Wire.available() > 0)
port = Wire.read();
return port;
}
/**
* Read the state of the 4 buttons.
* @return Bitmask with the 4 values: LSB - BUT1, MSB - BUT4
*/
uint8_t LCD16x2::readButtons(){
uint8_t buttons;
Wire.beginTransmission(ADDRESS);
Wire.write(GET_BUT);
Wire.endTransmission();
Wire.requestFrom((int)ADDRESS, 1);
while(Wire.available() > 0)
buttons = Wire.read();
return buttons;
}
/**
* Clear the LCD screen.
*/
void LCD16x2::lcdClear(){
Wire.beginTransmission(ADDRESS);
Wire.write(LCD_CLR);
Wire.endTransmission();
delay(100);
}
/**
* Position the cursor of the LCD to a given X and Y coordinates.
* @param x X coordinate
* @param y Y coordinate
*/
void LCD16x2::lcdGoToXY(uint8_t x, uint8_t y){
if(x > 16 || x < 1)
return;
else
X = x - 1;
if(y > 2)
return;
Y = y;
}
/**
* Write string to the LCD screen.
* @param string String to be written.
*/
void LCD16x2::lcdWrite(char* string){
uint8_t len;
uint8_t x, y;
x = X;
y = Y;
len = strlen(string);
for(int i = 0; i < len; i++){
Wire.beginTransmission(ADDRESS);
Wire.write(LCD_WR);
Wire.write(y);
Wire.write(x);
Wire.write(string[i]);
Wire.endTransmission();
delay(20);
x++;
if(x > 15){
x = 0;
y++;
if(y > 2)
return;
}
}
}
void LCD16x2::lcdWrite(int intVal){
String Str = String (intVal);
char charBuf[6];
Str.toCharArray(charBuf, 6);
lcdWrite(charBuf);
}
void LCD16x2::lcdWrite(float floatVal, uint8_t precision){
char charBuf[10];
dtostrf(floatVal, 3, precision, charBuf);
lcdWrite(charBuf);
}
code de démonstration:
#include <LCD16x2.h>
#include <Wire.h>
// On defini la LED sur l'Arduino UNO
#define LED 13
LCD16x2 lcd;
// Chaines de caractères
char text[32];
char textFull[64];
char space[17];
char choix[]= " Votre choix ? ";
char touches[]= "\176 \177 Eff OK";
char pub[]= "Bienvenue au LYCEE DORIAN";
void setup() {
// put your setup code here, to run once:
Wire.begin();
lcd.lcdClear();
lcd.lcdSetBlacklight(100);
lcd.lcdWrite(pub);
}
void loop() {
// put your main code here, to run repeatedly:
}
ou
(placer la lib LCD16X2 dans ......arduino-1.8.5/libraries
(LCD16x2.h et LCD16x2.cpp)
work@worktosh:/opt/arduino-1.8.5/libraries$ ls
Adafruit_Circuit_Playground Firmata LiquidCrystal Robot_Motor Stepper
Bridge GSM Mouse SD Temboo
Esplora Keyboard Robot_Control Servo TFT
Ethernet LCD16x2 RobotIRremote SpacebrewYun WiFi
work@worktosh:/opt/arduino-1.8.5/libraries$
Écrire un code qui permet de lire et d’écrire la touche enfoncée.
Pour valider la maîtrise du clavier 4 touches et de l'afficheur 2 lignes
Envoyer un code sur le PC par la liaison série.
Utilisation de la liaison série en 115200 b/s
L'arduino enverra la chaîne
Bonjour le monde
Verifier avec Putty
Puis écrire un code en C c89 , pour récupérer cette chaîne et l'afficher sur venant l'arduino
Envoyer un code du PC par la liaison série vers l'arduino. (qui affichera)
Utilisation de la liaison série en 115200 b/s
Le PC enverra la chaîne
"Bonjour le monde"
envoyer par le shell la chaîne. ( test)
Puis écrire un code en C c89 , qui enverra cette chaîne
Créer un code en C++ (Qt)
pour envoyer une chaîne sur l'afficheur. (utiliser un line edit)
et ajouter un bouton pour nettoyer l’écran (bouton clear)
ou pourra utiliser le caractère 17 pour cet ordre.
Un exemple d'utilisation de QSerialport est livré.