Vue normale

Contôler GPIO avec MySQL

Par : Kiwil
23 novembre 2015 à 20:01
Bonjour,

Aujourd'hui je vous propose un petit article sur l'utilisation facile des GPIO via MySQL, facile car une fois la base de donnée et le programme Python en marche il ne reste plus qu'à faire des petites requête SQL pour piloter ces GPIO. L’intérêt est qu'elle permet ensuite via n'importe quelle langage externe de faire ces requêtes sur votre Raspberry Pi pour contrôler les GPIO.

Le principe est simple un table avec trois colonnes suffisent, une pour le numéro de GPIO, une autre pour le mode IN/OUT, et la dernière pour l'état. L'autre avantage d'un système comme celui-ci c'est la possibilité d'adapter le système à n'importe quel plateforme (Arietta G25, BeagleBone, Raspberry Pi ...).

Le seule inconvénient dans ce type de  système c'est peu être le temps de réponse selon le langage et surtout le type de base de données, ici j'utilise du Python avec du MySQL mais du C avec du SQLite aurait surement été plus rapide. Mais personnellement ce type de système peut être utilisé pour par exemple des site web, ou le temps de réponse des GPIO n'est pas forcement la priorité.






Besoins

Pour l'utilisation de ce projet il nous faut tout d'abord deux choses, Python pour le programme et MySQL pour la base de données, je vous laisse ci cela n'est pas encore fait vous tourner vers votre moteur de recherche pour installer tout sa.

Il va nous falloir ensuite pour Python quelques librairie pour notamment ce connecter à la base de données MySQL. Pour ce faire il faut installer le paquet suivant :


sudo apt-get install python-mysqldb
 
Pour la partie MySQL, il faut créer dans un premier temps une base de donnée ci cela n'est déjà fait, avec la commande CREATE DATABASE GPIO dans MySQL. Nous créerons ensuite dans la suite la table.



Structure MySQL



Ci-dessous la structure de la table utilisé pour mon système :
CREATE TABLE IF NOT EXISTS `gpio` (
  `id_gpio` int(2) NOT NULL,
  `state` int(2) NOT NULL,
  `mode` int(2) NOT NULL,
  PRIMARY KEY (`id_gpio`)
)


Programme Python
 
Le programme est une boucle permanente sur tous les éléments de la table selon le mode, si ce mode est a 1 c'est à dire en entrée alors une lecture du GPIO est faite puis mis à jour dans la table, si ce mode est  à 0 alors l'écriture est fait dans l'état souhaiter si cette état à changé.


#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Import des modules
import RPi.GPIO as GPIO
import time
import MySQLdb

# Initialisation de la numerotation et des E/S
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

db   = MySQLdb.connect("localhost", "root", "raspberry", "GPIO_CONTROLE")
curs = db.cursor()

def Update_State_GPIO(iGPIO, iState):
   curs.execute("""UPDATE gpio SET state=%s WHERE id_gpio=%s""",(iState,iGPIO))

while True:
   time.sleep(0.15)
   # Pour toutes les GPIO de la base
   curs.execute("SELECT * FROM gpio")
   rows = curs.fetchall()
   for row in rows:
      if (row[3]==1):
         GPIO.setup(int(row[0]), GPIO.OUT)
         if (GPIO.input(row[0])!=int(row[2])):
            GPIO.output(int(row[0]), int(row[2]))

      else:
         GPIO.setup(int(row[0]), GPIO.IN)
         Update_State_GPIO(int(row[0]), GPIO.input(int(row[0])))
   db.commit()


Conclusion


Ci vous chercher un moyen simple de d’interagir avec les GPIO depuis n'importe quelle langage sans rechercher la rapidité de la microseconde de réponse, ce type de système est fait pour vous :D. Après, on peut imaginer des fonctions beaucoup plus complexe dans notre code Python, ainsi qu'une base de données plus structuré pour faire des lectures de température par exemple en paramétrant par exemple un mode 3 sur les GPIO, ou une table I2C en paramétrant les adresses dans celle-ci etc ...





Raspberry pi sur un drone

Par : Kiwil
26 juillet 2015 à 18:19
Bonjour,

Depuis quelques mois je me suis découvert une nouvelle passion pour les drones, je possède donc un petit drone de type 250 acheté en kit. Et avant d'investir dans un caméra et module fpv qui peu couter assez chère, je voulais faire quelques prise de vue. 

J'ai donc monté un Raspberry Pi A+ sur le drone, le choix de la version A+ était évidente puisque plus petite qu'une version normale. Avec bien sur une pi caméra, et un petit transformateur car la tension de la batterie du drone est de 11.1V.

Pour la programmation je n'ai pas fait un programme très complexe, puisque c'est un programme en Python avec la librairie pycamera qui démarre une capture vidéo lors du démarrage du système avec une simple tache cron. 

Le montage :





Le programme : 

Pour commencer on lit dans un fichier un numéro d'incrémentation puis on l'incrémente et on l'écrit dans le fichier, j'ai fait puisque on ne peut pas utiliser un simple nommage de fichier avec date/heure puisque au démarrage du système sans wifi la date et heure renvoyer sera toujours la même. On démarre ensuite la prise de la vidéo avec pour nom le numéro d'incrémentation récupér précédemment pour une durée indéfinie.

programme :

import picamera
import time
import RPi.GPIO as GPIO

# Definition de l'objet camera
camera = picamera.PiCamera()

# Lecture de l'incrementation fichier
ficR = open('/home/pi/Programme/Python/Video_Drone/Videos/INCR.txt','r+')
sINCR = ficR.read(3)
print sINCR
iINCR = int(sINCR)
ficR.close()

iINCR +=1

# Ecriture du fichier d'incrementation
ficW = open('/home/pi/Programme/Python/Video_Drone/Videos/INCR.txt','wb')
ficW.write(str(iINCR))
ficW.close()

camera.rotation = 180
camera.start_recording('/home/pi/Programme/Python/Video_Drone/Videos/Flight' + str(iINCR) + '.h264')

while (1):
        time.sleep(1)


La tache cron :
@reboot sudo python /home/pi/Programme/Python/Video_Drone/Video_Reboot.py

L’intérêt de cette tache est quelle ne s’exécute seulement au démarrage du RPI.

Une fois le vole terminé il faut simplement convertir la vidéo vers un format mp4 en installant  le packet suivant :
sudo apt-get install gpac

Et pour finir on lance la commande de conversion par exemple :
MP4Box -add ./Flight9.h264  ./Flight9.mp4


Première vidéo :

Pour le moment c'est la seule vidéo que j'ai peu prendre car il faut que je change un moteur ...

Arietta G25 - Librairie C++

Par : Kiwil
11 avril 2015 à 17:08
Bonjour,

Aujourd'hui je vous présente ma librairie pour utiliser les GPIO facilement dans votre programme C++. Car  jusqu'à présent la seul librairie était proposé par le créateur de l'arietta G25 et pour Python.


Présentation

La librairie est composée d'une classe nommé GPIO, et d'autre fonction hors classe. La classe principale comme sont nom l'indique permet de piloter les GPIO, pour le moment les fonctions principale sont testés et fonctionne correctement :

- pinMode(INPUT ou OUTPUT), permet d'affecter le sens de la broche.
- digitalWrite(HIGH ou LOW), permet d'écrire la valeur de sortie.
- digitalRead(), permet de lire la valeur de la broche en mode entrée.

Autre fonction hors classe :

- Delay(Milliseconde), fonction d'attente en milliseconde.
- readButton(), permet de lire l'état du bouton de l'Arietta G25.

D'autres fonctions sont à venir, l'utilisation des broches PWM, analogRead(), mode event pour les broches en entrée.

Utilisation

Le dépôt GitHub contient deux exemples, un simple Blink et un autre programme qui allume ou éteint en fonction de l'état du bouton.

Pour commencer deux façon d'initialiser un GPIO soit en passant directement une chaine avec le nom de la broche tel que définit par AcmeSystems (Ici), soit en passant un entier qui sera le Kernel Id de la broche (Disponible également le site).

Quelle intérêt dans par exemple pour GPIO led("A23") qui sera égale à GPIO led(23) me direz-vous ?
Tout simplement si l'ont regard pour la broche par exemple nommer C4 sont Kernel Id est égale à 68, donc à vous de choisir.

Blink :


#include "../Lib/libGPIO.h"
#include <stdio.h>
#include <stdlib.h>

int main()
{
    GPIO led("A23"); // "A23" ou kernel id = 23

    led.pinMode(OUTPUT);
    while(1)
    {
       Delay(250);
       led.digitalWrite(HIGH);
       Delay(250);
       led.digitalWrite(LOW);
    }

}

buttonRead() :


#include "../Lib/libGPIO.h"
#include <stdio.h>
#include <stdlib.h>

int main()
{
    GPIO led("A23"); // "A23" ou kernel id = 23

    led.pinMode(OUTPUT);
    while(1)
    { 
       led.digitalWrite(readButton());
    }

}


Compilation

Pour la compilation en attendant un makefile et une installation plus propre de la librairie dans votre systéme voici comment compiler, mais avant assurer vous que vous avez installé le compilateur c++.

Pour commencer télécharger la librairie :

git clone https://github.com/kkiwill/Arietta_G25_GPIO_Library.git

Ensuite on ce place dans le dossier Example pour compiler un des example :

cd ./Arietta_G25_GPIO_Library/Example

On compile ensuite le programme voulu avec :

g++ ./Blink.cpp ../Lib/libGPIO.cpp -o Blink -lrt

Si des personnes sont intéresser par le projet et souhaite y participer n’hésiter pas à me contacter.

Les sockets

Par : Kiwil
17 janvier 2015 à 19:12
Bonjour,

Depuis la création de l'application Windows et Android on me demande comment marche l'échange notamment du coté Raspberry Pi. Pour cela rien de très compliqué je créer un serveur de socket qui en fonction de chaque demande exécuter une commande, lit un GPIO ou écrit un GPIO.



Dernièrement j'ai fait évoluer se serveur de socket en utilisant une classe Python qui gère la réception de socket de façon événementielle. J'y intègre aussi une seconde classe qui me permet de récupérer facilement des informations système.

I - Le programme principale
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import Socket_Event
import subprocess
import RPi.GPIO as GPIO
from Sys_Info import *

# Variables globale
DEBUT_TRAME = "R"
FIN_TRAME   = "I"
SEPARATEUR  = chr(0x02)

# Reception de la trame et renvoie d'une autre
def TraiteRecv(self, data):
 # Variable
 ToSend = ""

 # Test si debut et fin de trame(pour vérification de trame complète)
 if (data[:1] == DEBUT_TRAME and data[-1:] == FIN_TRAME):
  data = data[1:len(data)-1]
  
  # Selon contenue
  if (data == "temp"):
   ToSend = str(get_temperature())

  if (data == "cpu"):
   ToSend = str(get_cpu_speed())

  if (data == "uptime"):
   ToSend = get_up_stats()[0]

  if (data == "ram"):
   ToSend = str(get_ram()[1])+' ('+str(get_ram()[0])+')'

  if (data == "nbproc"):
   ToSend = str(get_process_count())

  # GPIO mode
  if (data[0:2] == "GM"):
   try:
    mode = data[2:3]
    pin  = int(data[3::])
    if (mode == "I"):
     GPIO.setup(pin,GPIO.IN)
    else:
     GPIO.setup(pin,GPIO.OUT)
   except Exception, e:
    ToSend = ("Erreur_%s" % e)   
  # GPIO write
  if (data[0:2] == "GW"):
   try:
    etat = int(data[2:3])
    pin  = int(data[3::])
    if (etat == 1):
     GPIO.output(pin, GPIO.HIGH)
    else:
     GPIO.output(pin, GPIO.LOW)
   except Exception, e:
    ToSend = ("Erreur_%s" % e)
  # GPIO read
  if (data[0:2] == "GR"): 
   try:
    pin = int(data[2::])
    etat = GPIO.input(pin)
    ToSend = str(etat)
   except Exception, e:
    ToSend = ("Erreur_%s" % e)
  
  # On renvoie la donnée recu et la réponse (séparer par caract de 2)
  Socket_Event.EchoHandler.handle_write(self, DEBUT_TRAME + data + SEPARATEUR + ToSend + FIN_TRAME)    

# Definition de la socket
interface = "192.168.0.13"
port = 59004

# GPIO configuration
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)

# Lancement de la socket
server = Socket_Event.EchoServer((interface, port), TraiteRecv)
server.serve_forever()


Je commence par définir des variables global, celle-ci me permettrons de tester le début, fin de trames reçu pour être sur que ces dernières sont complètes. Ensuite la fonction qui sera appeller lors qu'une trame se présente dans la socket. Et pour finir aprés la fonction "TraiteRecv" la programme qui permet de définir l'IP de la socket ainsi que sont port, puis configurer les GPIO et pour finir lancer le serveur avec en paramètre l'IP, port et la fonction à appeler lorsque une trame est reçu. 

La fonction "TraiteRecv" dans un premier vérifie que le début et fin de trame sont présente dans la trame. On traite ensuite en fonction du message de la trame pour effectuer l'action demander, et pour finir on renvoie sur la socket la réponse que le client traitera à sont tour.

Les classes

La classe Socket_Event n'est pas de moi je l'ai juste modifier pour permettre d'avoir une fonction extérieur à la classe pour traiter les socket reçu.

La classe Sys_Infos est aussi une trouvaille du web.


Conclusions

 L'avantage de cette classe est donc sa simplicité d'utilisation, de plus les déconnexion du client sont automatiquement gérer par le serveur. Vous pouvez maintenant adapter tout sa à vos besoins d'objet connecter :-)

Le lien des fichier  : https://mega.co.nz/#!A9I2DaxD!qZVL9hzDwhWb5zP2LXqKIs_5cCFV-nRSNALtohtkruQ


Arietta G25 - Installation du système

Par : Kiwil
9 novembre 2014 à 13:57
Bonjour,

D'après le sondage et les quelques retour que j'en ai eu l'Arietta G25 semble intéresser les personnes qui souhaitent connaitre d'autre plateforme microcontrôleur Linux, c'est pourquoi je vais décrire les étapes pour bien commencer avec L'Arietta G25.

L'installation du système Debian n'est pas aussi simple que pour un Raspberry Pi, dû notamment pour le moment à sont manque de communauté. Je vais donc commencer par la l'installation du système.

Désolé pour les personnes utilisant Windows mais l'installation d'écrite par Acme-Systems se fait uniquement via un système  Linux.

Merci à Acme-Systems pour les tutoriels sur lesquels je me base pour faire le mien, qui sera simplement une adaptation en français.


I - Préparation de la carte SD

On va donc commencer par préparer la carte SD, c'est à dire que nous allons la formater puis la partitionner. Le tutoriel se fait via le système Ubuntu 13.10, mais vous pouvez reproduire se tutoriel sur n'importe quelle OS Linux.

Insérer votre carte SD, puis verifier que votre systéme à bien reconnnu la carte avec :
dmesg
Vous devriez retrouver à quelque chose prêt les lignes suivante :

[13736.699438] sd 15:0:0:0: [sdb] 3911680 512-byte logical blocks: (2.00 GB/1.86 GiB)
[13736.700061] sd 15:0:0:0: [sdb] Write Protect is off
[13736.700067] sd 15:0:0:0: [sdb] Mode Sense: 4b 00 00 08
[13736.700072] sd 15:0:0:0: [sdb] Assuming drive cache: write through
[13736.702662] sd 15:0:0:0: [sdb] Assuming drive cache: write through
[13736.702671]  sdb: sdb1
[13736.709301] sd 15:0:0:0: [sdb] Assuming drive cache: write through
[13736.709309] sd 15:0:0:0: [sdb] Attached SCSI removable disk

Ou [sdb] est le point de montage de la carte SD, on continue avec l'installation de GParted qui va nous permettre de formater puis partionner la carte. Pour l'installation ceci suffit :
sudo apt-get install GParted
Puis dans vos application lancer GParted, vous pouvez maintenant sélectionner votre carte SD et voir quelque chose comme le screenshot ci dessous :


 Ici par défaut la carte était formater en Fat16 avec une seule partition. Il faut commencer par supprimer la partition en cliquant droit dessus puis faire supprimer :


Nous allons maintenant créer 4 partitions  Kernel, rootfs, data, swap. On commence donc par Kernel, pour sa cliquer droit sur la "unallocated" et faire nouveau, et créer une partition comme ceci :

Taille: 32MB
Format: FAT16
Nom: kernel
Laisser les autres paramètre par défaut


Ensuite la partition rootfs, avec les paramètres suivant :

Taille: 800MB ou plus si selon la carte SD et se que vous compter installez par la suite.
Format: EXT4
Nom: rootfs
Laisser les autres paramètre par défaut


La partition Data qui va donc contenir vos donner, avec les paramètres suivant :

Format: EXT4
Espace libre: 128MB
Nom: data
Laisser les autres paramètre par défaut


Pour finir la partition swap, avec ceci :

Taille: 128MB
Format: linux-swap
Nom: swap
Laisser les autres paramètre par défaut


Voila le partitionnement est fini il faut maintenant l'appliquer avec le bouton vert qui se trouve juste au dessus des partitions. Une fois la fin des opérations retirer la carte et réinsérer la pour voir que 3 partitions sont bien monté.

Votre carte est maintenant prêt à recevoir le système pour la second partie.

II - Installation du système

Pour l'installation du système rien compliquer on va commencer par télécharger deux fichiers qui sont le kernel et le système rootfs, puis décompresser tout sa dans leurs partitions respective.

Téléchargement du kernel :
sudo wget http://www.acmesystems.it/download/microsd/Arietta-30aug2014/kernel.tar.bz2
Téléchargement de rootfs :
sudo wget http://www.acmesystems.it/download/microsd/Arietta-30aug2014/rootfs.tar.bz2
On va maintenant décompresser ces deux archives dans les partitions avec pour le kernel :
sudo tar -xvjpSf kernel.tar.bz2 -C /media/$USER/KERNEL  
Pour rootfs :
sudo tar -xvjpSf rootfs.tar.bz2 -C /media/$USER/rootfs
Penser à remplacer $USER par votre nom d'utilisateur :). Voila votre carte est prête à être démonter la carte SD puis brancher votre Arietta G25. Prochaine étape le premier démarrage.

III - Première  connexion

Pour la première connexion deux solutions, soit vous avez acheter la carte wifi dans se cas il faudra juste configurer le fichier "interfaces" sur votre carte SD avec vos paramètre de connexion Wifi. Autre solution connecter directement l'Arietta G25 à votre PC dans se cas il faut modifier le fichier "interfaces" de votre machine.

Cas Wifi :

Il faut donc monté la carte SD, et éditer le fichier "/etc/network/interfaces" pour éditer se fichier :
sudo nano /media/$USER/rootfs/etc/network/interfaces
Et éditer le fichier comme ceci :

auto wlan0
iface wlan0 inet dhcp
  wpa-ssid VOTRE_WIFI
  wpa-psk VOTRE_CLE

Démonter la carte SD puis brancher l'Arrietta G25 et voila ne reste plus qu'à chercher l'adresse IP et se connecter avec SSH (login : root, password : acmesystems).

Cas direct :

Ici ont va modifier les paramètres de connexion de la machine pour créer une sorte de réseau local, il faut donc la aussi éditer le fichier :
sudo nano /etc/network/interfaces
Puis ajouter les lignes suivantes :

allow-hotplug usb0
iface usb0 inet static
    address 192.168.10.20
    netmask 255.255.255.0

Brancher maintenant votre AG25, puis avec dmesg vérifier si les lignes suivantes apparaissent :

[54496.036265] usb 1-1: new high-speed USB device number 14 using ehci-pci
[54496.170886] usb 1-1: New USB device found, idVendor=0525, idProduct=a4a2
[54496.170889] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[54496.170891] usb 1-1: Product: RNDIS/Ethernet Gadget
[54496.170892] usb 1-1: Manufacturer: Linux 3.14.7+ with atmel_usba_udc 
[54496.299685] cdc_eem 1-1:1.0 usb0: register 'cdc_eem' at usb-0000:00:1d.7-1, CDC EEM Device, b2:2b:7d:e0:45:8e

Si ce n'est pas le cas essayer :

sudo ifup usb0
Un petit ping sur l'adresse 192.168.10.10, si sa ping c'est que tout est bon, ne reste plus qu'a s'y connecter ssh root@192.168.10.10 (login : root, password : acmesystems).






❌