Servo
PWM
Introduction
Bienvenue à cet atelier passionnant sur le système embarqué, où nous explorerons la magie du contrôle électronique à l'aide d'un microcontrôleur, d'un servo-moteur, d'un capteur infrarouge (PIR), et d'une LED. Notre parcours démarre avec une simulation fascinante, où nous allons créer une représentation visuelle d'un signal PWM (Pulse Width Modulation) sur un petit écran, accompagnée d'une fausse LED qui clignote pour illustrer le concept.
Au cours de cette première phase, nous allons plonger dans les bases du PWM, comprendre son rôle dans la modulation de la largeur des impulsions, et visualiser son impact sur la luminosité d'une LED. Cette simulation nous permettra de jeter les bases nécessaires pour la suite de notre atelier.
Une fois cette étape fonctionnelle, nous passerons à la pratique réelle. Dans la deuxième partie, nous allumerons une véritable LED en utilisant un PWM à une vitesse délibérément lente, créant ainsi un effet de clignotement perceptible. Cela nous permettra de mettre en pratique les concepts abordés dans la première phase et de voir comment le PWM peut être utilisé pour contrôler la luminosité d'une LED de manière dynamique.
Mais ça ne s'arrête pas là. Dans la troisième partie, nous explorerons le monde du mouvement contrôlé par le PWM en utilisant un servo-moteur. Nous découvrirons comment ajuster la position du servo-moteur en fonction du signal PWM, offrant ainsi une démonstration tangible de la polyvalence de cette technique de modulation.
Enfin, il y aura la quatrième et dernière phase, où nous intégrerons un capteur infrarouge (PIR) dans notre système. Dès qu'il détectera une présence, le PIR déclenchera une séquence d'événements passionnante : la LED s'allumera et le servo-moteur se mettra en mouvement. Cela démontre comment les systèmes embarqués peuvent réagir aux stimuli de leur environnement, illustrant ainsi la puissance et l'application pratique de ces technologies.
Les Besoins
- Un ordinateur
- Une connexion à Internet
- Une Oxocard Connect
- Un câble USB-USB type C
Quelques explications
Imagine que l'électricité circule dans un câble, un peu comme de l'eau dans un tuyau. Un signal 5V (volts) ou 0V est une façon de dire si l'électricité est "activée" ou "désactivée" dans ce tuyau. C'est le principe du binaire. Il n'y a que ces deux états dans notre cas.
-
5V (volts) : C'est comme dire "oui" à l'électricité. Quand le signal est à 5V, cela signifie que l'électricité est activée à fond. C'est comme si la lumière était allumée. C'est un 1 binaire.
-
0V : C'est comme dire "non" à l'électricité. Quand le signal est à 0V, cela signifie que l'électricité est désactivée. C'est comme si la lumière était éteinte. C'est un 0 binaire.
Maintenant, imagine que ce signal change entre 5V et 0V très rapidement. C'est comme si quelqu'un appuyait très rapidement sur l'interrupteur de la lumière pour l'allumer et l'éteindre très rapidement. Ce changement rapide crée le fameux signal PWM (modulation de largeur d'impulsion) dont nous avons parlé plus tôt.
Maintenant que tu sais que tu sais ce qu'est le binaire, il est temps de parler du principe de période. La période dans le contexte d'un signal électrique, comme celui utilisé dans la modulation de largeur d'impulsion (PWM), représente le temps nécessaire pour qu'une séquence complète se répète. C'est comme le cycle d'une animation qui recommence.
Imaginons que tu aies un interrupteur qui s'allume et s'éteint rapidement. La période serait le temps total entre un moment où l'interrupteur est allumé et le suivant où il est à nouveau allumé. Si l'interrupteur clignote très vite, la période est courte. Si le clignotement est plus lent, la période est plus longue.
Dans le cas du PWM, la période complète comprend à la fois le temps où le signal est actif (5V) et le temps où il est désactivé (0V). Le rapport entre le temps actif et le temps total de la période détermine la "largeur d'impulsion" et influence l'effet final, comme la luminosité d'une LED ou la position d'un servo-moteur.
Illustrons ça avec un schéma. Les lignes représentent un signal. Lorsque que le signal est en haut, c'est un 1 binaire et lorsqu'il est en bas il est à 0.
-
75% PWM : Dans cette partie de l'image, le signal est actif (5V) pendant 75% de la période et désactivé (0V) pendant le reste. C'est comme si quelqu'un appuyait rapidement sur l'interrupteur pour allumer la lumière et la laissait allumée pendant la plupart du temps avant de l'éteindre brièvement.
-
50% PWM : Au centre de l'image, le signal est actif pendant 50% de la période et désactivé pendant les 50% restants. Cela signifie que la lumière serait allumée et éteinte de manière égale, créant un effet de clignotement à une intensité moyenne.
-
25% PWM : Dans la dernière partie de l'image, le signal est actif pendant seulement 25% de la période et désactivé pendant les 75% restants. Cela donne l'impression que la lumière est allumée très brièvement avant d'être éteinte pour la majeure partie du temps.
L'image représente comment le signal électrique change dans le temps, créant différentes intensités lumineuses. Plus le signal est actif (proche de 100%), plus la lumière semble brillante, et plus il est inactif (proche de 0%), plus la lumière semble faible. Cette variation rapide crée l'effet de modulation de largeur d'impulsion (PWM), utilisé dans de nombreux dispositifs électroniques pour contrôler la luminosité, le mouvement et bien d'autres choses encore.
Le code
Dans cette partie tu va devoir trouver le code manquant à l'application afin de faire clignoter la LED dessinée à l'écran. La majeure partie du code est fournie. Il s'agit dans un premier temps copier le code donné et de le coller dans l'éditeur. Il est conseillé d'essayer de comprendre le code avec les explications donnés en dessous du code sur cette page. Rassurez-toi, la plupart des fonctions ne servent qu'à dessiner à l'écran.
#####################################
# Constantes and globales #
# variables to draw on the screen #
#####################################
const START_SCREEN_X = 0
const START_SCREEN_Y = 0
const HALF_SCREEN_X = 120
const HALF_SCREEN_Y = 120
const END_SCREEN_X = SCREEN_WIDTH
const END_SCREEN_Y = SCREEN_HEIGHT
const WIDTH = 28
const Y1 = 20
const Y2 = 40
const BRANCH_LENGTH_1 = 20
const BRANCH_LENGTH_2 = 30
const SPACE_FOR_BRANCH = WIDTH/4
const UP_STATE_SIZE = HALF_SCREEN_Y-30
const UP_STATE_DURATION = HALF_SCREEN_X+WIDTH
R:float = WIDTH/2
UP_STATE_SIZE_PWM = HALF_SCREEN_Y+50
DOWN_STATE_SIZE_PWM = HALF_SCREEN_Y+80
START_DRAW_PWM = START_SCREEN_X
END_DRAW_PWM = END_SCREEN_X
const HUE_RED = 255 # Hue needed for red in byte - H of HSV
const HUE_BLACK = 0 # Hue needed for black in byte - H of HSV
const SATURATION_MIN = 0 # Saturation at min in byte - S of HSV
const LUMINOSITY_MIN = 0 # Luminosity at min in byte - V of HSV
const SATURATION_MAX = 255 # Saturation at max in byte - S of HSV
const LUMINOSITY_MAX = 255 # Luminosity value at max in byte - V of HSV
#####################################
# Constantes and globales #
# variables for states and values #
#####################################
const OFF = 0 # HIGH state
const ON = 1 # LOW state
const PWM_VALUE = 64 # 1 .. 99
const CYCLE_EN_HERTZ = 1 # 1 .. 2
CYCLE_IN_SECONDS:float = 1 / CYCLE_EN_HERTZ
CYCLE_IN_MILISECONDS:float = CYCLE_IN_SECONDS*1000
#####################################
# Function to draw the LED #
# without light #
#####################################
def drawEmptyLED():
push()
strokeHSV(HUE_BLACK,SATURATION_MIN,LUMINOSITY_MAX)
fillHSV(HUE_BLACK,SATURATION_MIN,LUMINOSITY_MIN)
drawLine(HALF_SCREEN_X, Y1, HALF_SCREEN_X, Y2)
drawLine(HALF_SCREEN_X+WIDTH, Y1, HALF_SCREEN_X+WIDTH, Y2)
drawCircle(HALF_SCREEN_X+R, Y1, R)
noStroke()
drawRectangle(HALF_SCREEN_X+1, Y1+1, HALF_SCREEN_X+WIDTH-HALF_SCREEN_X-2, Y2-Y1-2)
drawLine(HALF_SCREEN_X, Y2, HALF_SCREEN_X+WIDTH, Y2)
drawLine(HALF_SCREEN_X+SPACE_FOR_BRANCH, Y2, HALF_SCREEN_X+SPACE_FOR_BRANCH, Y2+BRANCH_LENGTH_1)
drawLine(HALF_SCREEN_X+WIDTH-SPACE_FOR_BRANCH, Y2, HALF_SCREEN_X+WIDTH-SPACE_FOR_BRANCH, Y2+BRANCH_LENGTH_2)
pop()
#####################################
# Function to draw the positive #
# part of the signal #
#####################################
def drawUpSignal(hue, saturation, luminosity):
strokeHSV(hue, saturation, luminosity)
drawLine(START_SCREEN_X, HALF_SCREEN_Y, HALF_SCREEN_X, HALF_SCREEN_Y)
drawLine(HALF_SCREEN_X, HALF_SCREEN_Y, HALF_SCREEN_X, UP_STATE_SIZE)
drawLine(HALF_SCREEN_X, UP_STATE_SIZE, UP_STATE_DURATION, UP_STATE_SIZE)
drawLine(UP_STATE_DURATION, UP_STATE_SIZE, UP_STATE_DURATION, HALF_SCREEN_Y)
drawLine(UP_STATE_DURATION, HALF_SCREEN_Y, END_SCREEN_X, HALF_SCREEN_Y)
#####################################
# Function to draw the 0 #
# part of the signal #
#####################################
def drawDownSignal(hue, saturation, luminosity):
strokeHSV(hue, saturation, luminosity)
drawLine(START_SCREEN_X, HALF_SCREEN_Y, END_SCREEN_X, HALF_SCREEN_Y)
#####################################
# Function to draw the the signal #
#####################################
def drawSignal(upOrDown):
if upOrDown == ON:
drawDownSignal(HUE_BLACK,SATURATION_MIN,LUMINOSITY_MIN)
drawUpSignal(HUE_BLACK, SATURATION_MIN, LUMINOSITY_MAX)
else:
drawUpSignal(HUE_BLACK,SATURATION_MIN,LUMINOSITY_MIN)
drawDownSignal(HUE_BLACK, SATURATION_MIN, LUMINOSITY_MAX)
#####################################
# Function to draw the color in #
# the LED #
#####################################
def fillLEDColor(hue, saturation, luminosity):
noStroke()
fillHSV(hue,saturation,luminosity)
drawCircle(HALF_SCREEN_X+R, Y1+1, R)
drawRectangle(HALF_SCREEN_X+1, Y1+1, HALF_SCREEN_X+WIDTH-HALF_SCREEN_X-2, Y1-2)
if hue == HUE_RED:
drawSignal(ON)
else:
drawSignal(OFF)
update()
#####################################
# Function to draw a simple line #
# to split the screen #
#####################################
def drawSplitScreen():
strokeHSV(HUE_BLACK,SATURATION_MIN,LUMINOSITY_MAX)
drawLine(START_SCREEN_X, (HALF_SCREEN_Y/3)*2, END_SCREEN_X, (HALF_SCREEN_Y/3)*2)
#####################################
# Function used to calculate #
# the percentage of a max Value #
#####################################
def percentage(percent:long, maxValue:long)->long:
result = (percent/10*maxValue)/10
return result
######################################
# Function to draw the representation#
# of a PWM signal #
######################################
def drawPWM():
strokeHSV(HUE_BLACK,SATURATION_MIN,LUMINOSITY_MAX)
endPWMUpTime = START_DRAW_PWM+percentage(PWM_VALUE,END_SCREEN_X)
drawLine(START_DRAW_PWM, UP_STATE_SIZE_PWM, endPWMUpTime, UP_STATE_SIZE_PWM)
drawLine(endPWMUpTime, UP_STATE_SIZE_PWM,endPWMUpTime, DOWN_STATE_SIZE_PWM)
drawLine(endPWMUpTime, DOWN_STATE_SIZE_PWM, END_DRAW_PWM, DOWN_STATE_SIZE_PWM)
update()
######################################
# Initialisation function, used #
# first in the program. It draws the #
# elements on the screen #
######################################
def init():
drawEmptyLED()
drawSplitScreen()
drawPWM()
######################################
# Function make the led blink #
######################################
def blinkLEDScreen()
upTimeDelay = percentage(PWM_VALUE, CYCLE_IN_MILISECONDS)
while true:
fillLEDColor(HUE_RED, SATURATION_MAX, LUMINOSITY_MAX)
delay(upTimeDelay)
fillLEDColor(HUE_BLACK, SATURATION_MIN, LUMINOSITY_MIN)
delay(CYCLE_IN_MILISECONDS-upTimeDelay)
######################################
# The code should be written here #
######################################
#####################################
# SOMETHING TO INSERT HERE #
# to initialize and make #
# the LED blink #
####-----------------------------####
####-----------------------------####
Il ne reste plus qu'à appeler la fonction qui permet de faire clignoter la LED. Cette fonction met également à jour le dessin du signal.
Le Final
Le résultat est un affichage d'une LED qui s'allume et s'éteint en fonction du PWM sur l'écran
LED
Introduction
Maintenant que nous avons exploré la fascinante simulation du PWM avec une fausse LED, plongeons dans la réalité électrique avec une véritable diode électroluminescente, une LED ! Imaginez cette partie comme l'entrée dans le monde tangible de l'électronique, où nous allons appliquer concrètement les concepts que nous avons découverts jusqu'à présent.
Dans cette étape, nous allons jouer avec une LED réelle en utilisant le PWM pour créer un effet de clignotement. C'est comme si nous passons d'un dessin animé à une scène réelle, où la lumière brillera et s'éteindra sous notre contrôle. Nous allons ajuster la période, jouer avec la largeur d'impulsion et observer comment ces changements influent sur la luminosité de la LED.
Les Besoins
- Un ordinateur
- Une connexion à Internet
- Une Oxocard Connect avec sa breadboard
- Un câble USB-USB type C
Il est également nécessaire d'avoir les composants électroniques suivants pour cette étape ainsi que les 2 prochaines :
L'image suivante peut aider à faire le montage, il est facile de se perdre et de mettre une pin au mauvais endroit dans ce gerne de cas.
La vidéo suivante montre comment câbler les composants sur la breadboard afin que le circuit corresponde au code :
Vous devriez alors avoir le montage suivant :
Vous êtes dès à présent prêts à coder !
Le code
Dans cette partie vous allez devoir trouver le code manquant à l'application afin de faire clignoter la vrai LED :
#####################################
# Constantes and globales #
# variables to draw on the screen #
#####################################
const START_SCREEN_X = 0
const START_SCREEN_Y = 0
const HALF_SCREEN_X = 120
const HALF_SCREEN_Y = 120
const END_SCREEN_X = SCREEN_WIDTH
const END_SCREEN_Y = SCREEN_HEIGHT
const WIDTH = 28
const Y1 = 20
const Y2 = 40
const BRANCH_LENGTH_1 = 20
const BRANCH_LENGTH_2 = 30
const SPACE_FOR_BRANCH = WIDTH/4
const UP_STATE_SIZE = HALF_SCREEN_Y-30
const UP_STATE_DURATION = HALF_SCREEN_X+WIDTH
R:float = WIDTH/2
UP_STATE_SIZE_PWM = HALF_SCREEN_Y+50
DOWN_STATE_SIZE_PWM = HALF_SCREEN_Y+80
START_DRAW_PWM = START_SCREEN_X
END_DRAW_PWM = END_SCREEN_X
const HUE_RED = 255 # Hue needed for red in byte - H of HSV
const HUE_BLACK = 0 # Hue needed for black in byte - H of HSV
const SATURATION_MIN = 0 # Saturation at min in byte - S of HSV
const LUMINOSITY_MIN = 0 # Luminosity at min in byte - V of HSV
const SATURATION_MAX = 255 # Saturation at max in byte - S of HSV
const LUMINOSITY_MAX = 255 # Luminosity value at max in byte - V of HSV
#####################################
# Constantes and globales #
# variables for states and values #
#####################################
const OFF = 0 # HIGH state
const ON = 1 # LOW state
const PWM_VALUE = 50 # 1 .. 99
const CYCLE_IN_HERTZ = 1
const MAX_DUTYCYCLE = 4096
CYCLE_IN_SECONDS:float = 1 / CYCLE_IN_HERTZ
CYCLE_IN_MILISECONDS:float = CYCLE_IN_SECONDS*1000
dutyCycle:int = 2048 # 0..4096
#####################################
# Constantes and globales #
# variables for IO #
#####################################
const LED_RED_PIN = C_PIN_05 # LED on IO05
#####################################
# Function to draw the LED #
# without light #
#####################################
def drawEmptyLED():
push()
strokeHSV(HUE_BLACK,SATURATION_MIN,LUMINOSITY_MAX)
fillHSV(HUE_BLACK,SATURATION_MIN,LUMINOSITY_MIN)
drawLine(HALF_SCREEN_X, Y1, HALF_SCREEN_X, Y2)
drawLine(HALF_SCREEN_X+WIDTH, Y1, HALF_SCREEN_X+WIDTH, Y2)
drawCircle(HALF_SCREEN_X+R, Y1, R)
noStroke()
drawRectangle(HALF_SCREEN_X+1, Y1+1, HALF_SCREEN_X+WIDTH-HALF_SCREEN_X-2, Y2-Y1-2)
drawLine(HALF_SCREEN_X, Y2, HALF_SCREEN_X+WIDTH, Y2)
drawLine(HALF_SCREEN_X+SPACE_FOR_BRANCH, Y2, HALF_SCREEN_X+SPACE_FOR_BRANCH, Y2+BRANCH_LENGTH_1)
drawLine(HALF_SCREEN_X+WIDTH-SPACE_FOR_BRANCH, Y2, HALF_SCREEN_X+WIDTH-SPACE_FOR_BRANCH, Y2+BRANCH_LENGTH_2)
pop()
#####################################
# Function to draw the positive #
# part of the signal #
#####################################
def drawUpSignal(hue, saturation, luminosity):
strokeHSV(hue, saturation, luminosity)
drawLine(START_SCREEN_X, HALF_SCREEN_Y, HALF_SCREEN_X, HALF_SCREEN_Y)
drawLine(HALF_SCREEN_X, HALF_SCREEN_Y, HALF_SCREEN_X, UP_STATE_SIZE)
drawLine(HALF_SCREEN_X, UP_STATE_SIZE, UP_STATE_DURATION, UP_STATE_SIZE)
drawLine(UP_STATE_DURATION, UP_STATE_SIZE, UP_STATE_DURATION, HALF_SCREEN_Y)
drawLine(UP_STATE_DURATION, HALF_SCREEN_Y, END_SCREEN_X, HALF_SCREEN_Y)
#####################################
# Function to draw the 0 #
# part of the signal #
#####################################
def drawDownSignal(hue, saturation, luminosity):
strokeHSV(hue, saturation, luminosity)
drawLine(START_SCREEN_X, HALF_SCREEN_Y, END_SCREEN_X, HALF_SCREEN_Y)
#####################################
# Function to draw the the signal #
#####################################
def drawSignal(upOrDown):
if upOrDown == ON:
drawDownSignal(HUE_BLACK,SATURATION_MIN,LUMINOSITY_MIN)
drawUpSignal(HUE_BLACK, SATURATION_MIN, LUMINOSITY_MAX)
else:
drawUpSignal(HUE_BLACK,SATURATION_MIN,LUMINOSITY_MIN)
drawDownSignal(HUE_BLACK, SATURATION_MIN, LUMINOSITY_MAX)
#####################################
# Function to draw the color in #
# the LED #
#####################################
def fillLEDColor(hue, saturation, luminosity):
noStroke()
fillHSV(hue,saturation,luminosity)
drawCircle(HALF_SCREEN_X+R, Y1+1, R)
drawRectangle(HALF_SCREEN_X+1, Y1+1, HALF_SCREEN_X+WIDTH-HALF_SCREEN_X-2, Y1-2)
if hue == HUE_RED:
drawSignal(ON)
else:
drawSignal(OFF)
update()
#####################################
# Function to draw a simple line #
# to split the screen #
#####################################
def drawSplitScreen():
strokeHSV(HUE_BLACK,SATURATION_MIN,LUMINOSITY_MAX)
drawLine(START_SCREEN_X, (HALF_SCREEN_Y/3)*2, END_SCREEN_X, (HALF_SCREEN_Y/3)*2)
#####################################
# Function used to calculate #
# the percentage of a max Value #
#####################################
def percentage(percent:long, maxValue:long)->long:
result = (percent/10*maxValue)/10
return result
######################################
# Function to draw the representation#
# of a PWM signal #
######################################
def drawPWM():
strokeHSV(HUE_BLACK,SATURATION_MIN,LUMINOSITY_MAX)
endPWMUpTime = START_DRAW_PWM+percentage(PWM_VALUE,END_SCREEN_X)
drawLine(START_DRAW_PWM, UP_STATE_SIZE_PWM, endPWMUpTime, UP_STATE_SIZE_PWM)
drawLine(endPWMUpTime, UP_STATE_SIZE_PWM,endPWMUpTime, DOWN_STATE_SIZE_PWM)
drawLine(endPWMUpTime, DOWN_STATE_SIZE_PWM, END_DRAW_PWM, DOWN_STATE_SIZE_PWM)
update()
######################################
# Initialisation function, used #
# first in the program. It draws the #
# elements on the screen #
######################################
def init():
drawEmptyLED()
drawSplitScreen()
drawPWM()
initGPIO(LED_RED_PIN, OUTPUT) # LED is an output
setPWMFrequency(CYCLE_IN_HERTZ)
dutyCycle = percentage(PWM_VALUE, MAX_DUTYCYCLE)
#####################################
# The code should be written here #
# SOMETHING TO INSERT #
# to initialize and make #
# the LED blink #
# SOMETHING TO INSERT here #
####-----------------------------####
####-----------------------------####
######################################
# Function make the led on screen #
# blink #
######################################
init()
upTimeDelay = percentage(PWM_VALUE, CYCLE_IN_MILISECONDS)
def onDraw():
fillLEDColor(HUE_RED, SATURATION_MAX, LUMINOSITY_MAX)
delay(upTimeDelay)
fillLEDColor(HUE_BLACK, SATURATION_MIN, LUMINOSITY_MIN)
delay(CYCLE_IN_MILISECONDS-upTimeDelay)
Il ne manque qu'une seule ligne afin de faire fonctionner le clignotement de la LED. Cette ligne sert à lier le taux du PWM à la sortie IO05.
Le Final
Le résultat est alors une LED qui clignote. Tu peux voir qu'il y a une désynchronisation avec celle qui s'affiche malgré le fait que le PWM est lié à la LED. C'est dû au fait que la led dessinée n'est qu'une simulation et ne respecte pas réellement le timing.
Moteur
Introduction
Maintenant que nous avons exploré la magie du contrôle lumineux avec notre véritable LED, il est temps d'ajouter du mouvement à notre aventure électronique. Dans cette phase captivante, nous allons plonger dans le monde du servo-moteur, un dispositif électronique qui peut tourner dans une direction précise sous l'influence du PWM.
Imaginez-vous aux commandes d'un petit robot, capable de faire des mouvements précis grâce à une combinaison intelligente de signaux électriques. C'est exactement ce que nous allons réaliser avec notre servo-moteur ! Nous allons explorer comment le PWM peut être utilisé pour positionner et faire bouger mécaniquement le servo-moteur, apportant une dimension physique et interactive à notre atelier.
Les Besoins
- Un ordinateur
- Une connexion à Internet
- Une Oxocard Connect avec sa breadboard
- Un câble USB-USB type C
Il est également nécessaire d'avoir les composants électroniques suivants pour cette étapes ainsi que la prochaine :
L'image suivante peut aider à faire le montage, il est facile de se perdre et de mettre une pin au mauvais endroit dans ce gerne de cas.
La vidéo suivante montre comment câbler les composants sur la breadboard afin que le circuit corresponde au code :
Vous devriez alors avoir le montage suivant, sans le PIR :
Vous êtes dès à présent prêts à coder !
Le code
Dans cette partie vous allez devoir trouver le code manquant à l'application afin de faire clignoter la LED dessinée à l'écran :
#####################################
# Constantes and globales #
# variables to draw on the screen #
#####################################
const START_SCREEN_X = 0
const START_SCREEN_Y = 0
const HALF_SCREEN_X = 120
const HALF_SCREEN_Y = 120
const END_SCREEN_X = SCREEN_WIDTH
const END_SCREEN_Y = SCREEN_HEIGHT
const WIDTH = 28
const Y1 = 20
const Y2 = 40
const BRANCH_LENGTH_1 = 20
const BRANCH_LENGTH_2 = 30
const SPACE_FOR_BRANCH = WIDTH/4
const UP_STATE_SIZE = HALF_SCREEN_Y-30
const UP_STATE_DURATION = HALF_SCREEN_X+WIDTH
R:float = WIDTH/2
UP_STATE_SIZE_PWM = HALF_SCREEN_Y+50
DOWN_STATE_SIZE_PWM = HALF_SCREEN_Y+80
START_DRAW_PWM = START_SCREEN_X
END_DRAW_PWM = END_SCREEN_X
const HUE_RED = 255 # Hue needed for red in byte - H of HSV
const HUE_BLACK = 0 # Hue needed for black in byte - H of HSV
const SATURATION_MIN = 0 # Saturation at min in byte - S of HSV
const LUMINOSITY_MIN = 0 # Luminosity at min in byte - V of HSV
const SATURATION_MAX = 255 # Saturation at max in byte - S of HSV
const LUMINOSITY_MAX = 255 # Luminosity value at max in byte - V of HSV
#####################################
# Constantes and globales #
# variables for states and values #
#####################################
const OFF = 0 # HIGH state
const ON = 1 # LOW state
const PWM_VALUE = 50 # Servo runs on 50Hz
const CYCLE_IN_HERTZ = 1
const MAX_DUTYCYCLE = 4096
# PWM resolution = 12bit --> 0 - 4096
# 90deg Servo signal = 50Hz, Duty cycle 2.5%-12.5% => -90 - +90 deg
# 2.5% PWM = 4096 * 0.025 = 102
# 12.5% PWM = 4096 * 0.125 = 512
# --> -90 - +90 deg = 102 - 512
const ANGLE_90 = 512 # 512 is about +90 degrees
const ANGLE_0 = 102 # 102 is about -90 degrees
CYCLE_IN_SECONDS:float = 1 / CYCLE_IN_HERTZ
CYCLE_IN_MILISECONDS:float = CYCLE_IN_SECONDS*1000
dutyCycle:int = 2048 # 0..4096
#####################################
# Constantes and globales #
# variables for IO #
#####################################
const LED_RED_PIN = C_PIN_05 # LED on IO05
const SERVO_PIN = C_PIN_01 # Servo on IO01
#####################################
# Function to draw the LED #
# without light #
#####################################
def drawEmptyLED():
push()
strokeHSV(HUE_BLACK,SATURATION_MIN,LUMINOSITY_MAX)
fillHSV(HUE_BLACK,SATURATION_MIN,LUMINOSITY_MIN)
drawLine(HALF_SCREEN_X, Y1, HALF_SCREEN_X, Y2)
drawLine(HALF_SCREEN_X+WIDTH, Y1, HALF_SCREEN_X+WIDTH, Y2)
drawCircle(HALF_SCREEN_X+R, Y1, R)
noStroke()
drawRectangle(HALF_SCREEN_X+1, Y1+1, HALF_SCREEN_X+WIDTH-HALF_SCREEN_X-2, Y2-Y1-2)
drawLine(HALF_SCREEN_X, Y2, HALF_SCREEN_X+WIDTH, Y2)
drawLine(HALF_SCREEN_X+SPACE_FOR_BRANCH, Y2, HALF_SCREEN_X+SPACE_FOR_BRANCH, Y2+BRANCH_LENGTH_1)
drawLine(HALF_SCREEN_X+WIDTH-SPACE_FOR_BRANCH, Y2, HALF_SCREEN_X+WIDTH-SPACE_FOR_BRANCH, Y2+BRANCH_LENGTH_2)
pop()
#####################################
# Function to draw the positive #
# part of the signal #
#####################################
def drawUpSignal(hue, saturation, luminosity):
strokeHSV(hue, saturation, luminosity)
drawLine(START_SCREEN_X, HALF_SCREEN_Y, HALF_SCREEN_X, HALF_SCREEN_Y)
drawLine(HALF_SCREEN_X, HALF_SCREEN_Y, HALF_SCREEN_X, UP_STATE_SIZE)
drawLine(HALF_SCREEN_X, UP_STATE_SIZE, UP_STATE_DURATION, UP_STATE_SIZE)
drawLine(UP_STATE_DURATION, UP_STATE_SIZE, UP_STATE_DURATION, HALF_SCREEN_Y)
drawLine(UP_STATE_DURATION, HALF_SCREEN_Y, END_SCREEN_X, HALF_SCREEN_Y)
#####################################
# Function to draw the 0 #
# part of the signal #
#####################################
def drawDownSignal(hue, saturation, luminosity):
strokeHSV(hue, saturation, luminosity)
drawLine(START_SCREEN_X, HALF_SCREEN_Y, END_SCREEN_X, HALF_SCREEN_Y)
#####################################
# Function to draw the the signal #
#####################################
def drawSignal(upOrDown):
if upOrDown == ON:
drawDownSignal(HUE_BLACK,SATURATION_MIN,LUMINOSITY_MIN)
drawUpSignal(HUE_BLACK, SATURATION_MIN, LUMINOSITY_MAX)
else:
drawUpSignal(HUE_BLACK,SATURATION_MIN,LUMINOSITY_MIN)
drawDownSignal(HUE_BLACK, SATURATION_MIN, LUMINOSITY_MAX)
#####################################
# Function to draw the color in #
# the LED #
#####################################
def fillLEDColor(hue, saturation, luminosity):
noStroke()
fillHSV(hue,saturation,luminosity)
drawCircle(HALF_SCREEN_X+R, Y1+1, R)
drawRectangle(HALF_SCREEN_X+1, Y1+1, HALF_SCREEN_X+WIDTH-HALF_SCREEN_X-2, Y1-2)
if hue == HUE_RED:
drawSignal(ON)
else:
drawSignal(OFF)
update()
#####################################
# Function to draw a simple line #
# to split the screen #
#####################################
def drawSplitScreen():
strokeHSV(HUE_BLACK,SATURATION_MIN,LUMINOSITY_MAX)
drawLine(START_SCREEN_X, (HALF_SCREEN_Y/3)*2, END_SCREEN_X, (HALF_SCREEN_Y/3)*2)
#####################################
# Function used to calculate #
# the percentage of a max Value #
#####################################
def percentage(percent:long, maxValue:long)->long:
result = (percent/10*maxValue)/10
return result
######################################
# Function to draw the representation#
# of a PWM signal #
######################################
def drawPWM():
strokeHSV(HUE_BLACK,SATURATION_MIN,LUMINOSITY_MAX)
endPWMUpTime = START_DRAW_PWM+percentage(PWM_VALUE,END_SCREEN_X)
drawLine(START_DRAW_PWM, UP_STATE_SIZE_PWM, endPWMUpTime, UP_STATE_SIZE_PWM)
drawLine(endPWMUpTime, UP_STATE_SIZE_PWM,endPWMUpTime, DOWN_STATE_SIZE_PWM)
drawLine(endPWMUpTime, DOWN_STATE_SIZE_PWM, END_DRAW_PWM, DOWN_STATE_SIZE_PWM)
update()
######################################
# Initialisation function, used #
# first in the program. It draws the #
# elements on the screen #
######################################
def init():
drawEmptyLED()
drawSplitScreen()
drawPWM()
initGPIO(LED_RED_PIN, OUTPUT) # LED is an output
setPWMFrequency(PWM_VALUE)
######################################
# Function make the led on screen #
# blink #
######################################
init()
upTimeDelay = percentage(PWM_VALUE, CYCLE_IN_MILISECONDS)
def onDraw():
fillLEDColor(HUE_RED, SATURATION_MAX, LUMINOSITY_MAX)
#####################################
# The code should be written here #
# SOMETHING TO INSERT #
# to make the motor move 180° #
# SOMETHING TO INSERT here #
####-----------------------------####
####-----------------------------####
writeGPIO(LED_RED_PIN, ON)
delay(upTimeDelay)
fillLEDColor(HUE_BLACK, SATURATION_MIN, LUMINOSITY_MIN)
#####################################
# SOMETHING TO INSERT here also #
####-----------------------------####
####-----------------------------####
writeGPIO(LED_RED_PIN, OFF)
delay(CYCLE_IN_MILISECONDS-upTimeDelay)
Cette fois-ci il y a 2 lignes à trouver. Il faut utiliser la même fonction que précédemment mais cette fois-ci il faut l'attribuer à la pin du servo moteur et lui donner l'angle qu'il doit faire. Pense à utiliser les constantes en haut du code.
Le Final
Le résultat est alors une LED qui clignote au même rythme que les mouvements du servo moteur.
PIR
Introduction
Après avoir illuminé notre chemin avec la LED et animé notre atelier avec le mouvement du servo-moteur, il est temps d'introduire un élément interactif qui va donner à notre système embarqué une perception sensorielle. Bienvenue à la phase finale, où nous allons explorer les capacités du capteur infrarouge, ou PIR (Passive Infrared Sensor).
Imaginez maintenant que notre système embarqué acquiert une sorte de "sensibilité" à son environnement. Le PIR, un détecteur de mouvement, va être notre œil électronique capable de percevoir des changements dans la chaleur ambiante. Lorsque le PIR détecte quelque chose en mouvement, notre système embarqué réagira en allumant la LED et en mettant le servo-moteur en action. C'est comme si nous ajoutions une touche d'intelligence à notre création, lui permettant de répondre aux stimuli extérieurs.
Les Besoins
- Un ordinateur
- Une connexion à Internet
- Une Oxocard Connect avec sa breadboard
- Un câble USB-USB type C
Il est également nécessaire d'avoir les composants électroniques suivants :
L'image suivante peut aider à faire le montage, il est facile de se perdre et de mettre une pin au mauvais endroit dans ce gerne de cas.
La vidéo suivante montre comment câbler les composants sur la breadboard afin que le circuit corresponde au code :
Vous devriez alors avoir le montage suivant :
Vous êtes dès à présent prêts à coder !
Le code
Dans cette partie vous allez devoir trouver le code manquant à l'application :
#####################################
# Constantes and globales #
# variables to draw on the screen #
#####################################
const START_SCREEN_X = 0
const START_SCREEN_Y = 0
const HALF_SCREEN_X = 120
const HALF_SCREEN_Y = 120
const END_SCREEN_X = SCREEN_WIDTH
const END_SCREEN_Y = SCREEN_HEIGHT
const WIDTH = 28
const Y1 = 20
const Y2 = 40
const BRANCH_LENGTH_1 = 20
const BRANCH_LENGTH_2 = 30
const SPACE_FOR_BRANCH = WIDTH/4
const UP_STATE_SIZE = HALF_SCREEN_Y-30
const UP_STATE_DURATION = HALF_SCREEN_X+WIDTH
R:float = WIDTH/2
UP_STATE_SIZE_PWM = HALF_SCREEN_Y+50
DOWN_STATE_SIZE_PWM = HALF_SCREEN_Y+80
START_DRAW_PWM = START_SCREEN_X
END_DRAW_PWM = END_SCREEN_X
const HUE_RED = 255 # Hue needed for red in byte - H of HSV
const HUE_BLACK = 0 # Hue needed for black in byte - H of HSV
const SATURATION_MIN = 0 # Saturation at min in byte - S of HSV
const LUMINOSITY_MIN = 0 # Luminosity at min in byte - V of HSV
const SATURATION_MAX = 255 # Saturation at max in byte - S of HSV
const LUMINOSITY_MAX = 255 # Luminosity value at max in byte - V of HSV
#####################################
# Constantes and globales #
# variables for states and values #
#####################################
const OFF = 0 # HIGH state
const ON = 1 # LOW state
const PWM_VALUE = 50 # Servo runs on 50Hz
const CYCLE_IN_HERTZ = 1
const MAX_DUTYCYCLE = 4096
# PWM resolution = 12bit --> 0 - 4096
# 90deg Servo signal = 50Hz, Duty cycle 2.5%-12.5% => -90 - +90 deg
# 2.5% PWM = 4096 * 0.025 = 102
# 12.5% PWM = 4096 * 0.125 = 512
# --> -90 - +90 deg = 102 - 512
const ANGLE_90 = 307 # 512 is about +90 degrees
const ANGLE_0 = 102 # 102 is about -90 degrees
CYCLE_IN_SECONDS:float = 1 / CYCLE_IN_HERTZ
CYCLE_IN_MILISECONDS:float = CYCLE_IN_SECONDS*1000
dutyCycle:int = 2048 # 0..4096
#####################################
# Constantes and globales #
# variables for IO #
#####################################
const LED_RED_PIN = C_PIN_05 # LED on IO05
const SERVO_PIN = C_PIN_01 # Servo on IO01
const PIR_PIN = C_PIN_06 # PIR sensor on IN06
#####################################
# Function to draw the LED #
# without light #
#####################################
def drawEmptyLED():
push()
strokeHSV(HUE_BLACK,SATURATION_MIN,LUMINOSITY_MAX)
fillHSV(HUE_BLACK,SATURATION_MIN,LUMINOSITY_MIN)
drawLine(HALF_SCREEN_X, Y1, HALF_SCREEN_X, Y2)
drawLine(HALF_SCREEN_X+WIDTH, Y1, HALF_SCREEN_X+WIDTH, Y2)
drawCircle(HALF_SCREEN_X+R, Y1, R)
noStroke()
drawRectangle(HALF_SCREEN_X+1, Y1+1, HALF_SCREEN_X+WIDTH-HALF_SCREEN_X-2, Y2-Y1-2)
drawLine(HALF_SCREEN_X, Y2, HALF_SCREEN_X+WIDTH, Y2)
drawLine(HALF_SCREEN_X+SPACE_FOR_BRANCH, Y2, HALF_SCREEN_X+SPACE_FOR_BRANCH, Y2+BRANCH_LENGTH_1)
drawLine(HALF_SCREEN_X+WIDTH-SPACE_FOR_BRANCH, Y2, HALF_SCREEN_X+WIDTH-SPACE_FOR_BRANCH, Y2+BRANCH_LENGTH_2)
pop()
#####################################
# Function to draw the positive #
# part of the signal #
#####################################
def drawUpSignal(hue, saturation, luminosity):
strokeHSV(hue, saturation, luminosity)
drawLine(START_SCREEN_X, HALF_SCREEN_Y, HALF_SCREEN_X, HALF_SCREEN_Y)
drawLine(HALF_SCREEN_X, HALF_SCREEN_Y, HALF_SCREEN_X, UP_STATE_SIZE)
drawLine(HALF_SCREEN_X, UP_STATE_SIZE, UP_STATE_DURATION, UP_STATE_SIZE)
drawLine(UP_STATE_DURATION, UP_STATE_SIZE, UP_STATE_DURATION, HALF_SCREEN_Y)
drawLine(UP_STATE_DURATION, HALF_SCREEN_Y, END_SCREEN_X, HALF_SCREEN_Y)
#####################################
# Function to draw the 0 #
# part of the signal #
#####################################
def drawDownSignal(hue, saturation, luminosity):
strokeHSV(hue, saturation, luminosity)
drawLine(START_SCREEN_X, HALF_SCREEN_Y, END_SCREEN_X, HALF_SCREEN_Y)
#####################################
# Function to draw the the signal #
#####################################
def drawSignal(upOrDown):
if upOrDown == ON:
drawDownSignal(HUE_BLACK,SATURATION_MIN,LUMINOSITY_MIN)
drawUpSignal(HUE_BLACK, SATURATION_MIN, LUMINOSITY_MAX)
else:
drawUpSignal(HUE_BLACK,SATURATION_MIN,LUMINOSITY_MIN)
drawDownSignal(HUE_BLACK, SATURATION_MIN, LUMINOSITY_MAX)
#####################################
# Function to draw the color in #
# the LED #
#####################################
def fillLEDColor(hue, saturation, luminosity):
noStroke()
fillHSV(hue,saturation,luminosity)
drawCircle(HALF_SCREEN_X+R, Y1+1, R)
drawRectangle(HALF_SCREEN_X+1, Y1+1, HALF_SCREEN_X+WIDTH-HALF_SCREEN_X-2, Y1-2)
if hue == HUE_RED:
drawSignal(ON)
else:
drawSignal(OFF)
update()
#####################################
# Function to draw a simple line #
# to split the screen #
#####################################
def drawSplitScreen():
strokeHSV(HUE_BLACK,SATURATION_MIN,LUMINOSITY_MAX)
drawLine(START_SCREEN_X, (HALF_SCREEN_Y/3)*2, END_SCREEN_X, (HALF_SCREEN_Y/3)*2)
#####################################
# Function used to calculate #
# the percentage of a max Value #
#####################################
def percentage(percent:long, maxValue:long)->long:
result = (percent/10*maxValue)/10
return result
######################################
# Function to draw the representation#
# of a PWM signal #
######################################
def drawPWM():
strokeHSV(HUE_BLACK,SATURATION_MIN,LUMINOSITY_MAX)
endPWMUpTime = START_DRAW_PWM+percentage(PWM_VALUE,END_SCREEN_X)
drawLine(START_DRAW_PWM, UP_STATE_SIZE_PWM, endPWMUpTime, UP_STATE_SIZE_PWM)
drawLine(endPWMUpTime, UP_STATE_SIZE_PWM,endPWMUpTime, DOWN_STATE_SIZE_PWM)
drawLine(endPWMUpTime, DOWN_STATE_SIZE_PWM, END_DRAW_PWM, DOWN_STATE_SIZE_PWM)
update()
######################################
# Initialisation function, used #
# first in the program. It draws the #
# elements on the screen #
######################################
def init():
drawEmptyLED()
drawSplitScreen()
drawPWM()
initGPIO(LED_RED_PIN, OUTPUT) # LED is an output
initGPIO(PIR_PIN, INPUT) # PIR is an input
setPWMFrequency(PWM_VALUE)
######################################
# Function make the led on screen #
# blink and init GPIO and PWM #
######################################
init()
def onDraw():
#####################################
# The code should be written here #
# SOMETHING TO INSERT #
# to make the motor move 90° #
# SOMETHING TO INSERT here #
####-----------------------------####
if readGPIO(...)
####-----------------------------####
writeGPIO(LED_RED_PIN, ON) # HIGH
writePWM(SERVO_PIN, ANGLE_90)
fillLEDColor(HUE_RED, SATURATION_MAX, LUMINOSITY_MAX)
else:
writeGPIO(LED_RED_PIN, OFF) # LOW
writePWM(SERVO_PIN, ANGLE_0)
fillLEDColor(HUE_BLACK, SATURATION_MIN, LUMINOSITY_MIN)
##################################
Il n'y a qu'une seule ligne de code à trouver cette fois. Le principe reste le même que d'habitude mais aucune autre aide n'est donnée cette fois.
Le Final
Le résultat est alors une LED qui s'allume et un moteur qui bouge lorsque le détecteur capte un mouvement.
Bravo tu es arrivé à la fin de cet atelier et tu en sais désormais plus sur la programmation de systèmes embarqués. Si tu désires continuer avec cet environnement de développement, tu peux te procurer ton propre kit OXOCARD Connect ici : https://shop.oxon.ch/?shop=oxocard-connect&lang=fr