Ma réflexion sur le code Arduino :
Voici une bonne structure de base "machine d'état" :
http://pinballmakers.com/wiki/index.php/Programming
http://forum.locoduino.org/index.php?to ... 763#msg763
La modélisation d'un système par machine d'états-transitions est, à ma connaissance, un des moyens les plus efficaces pour analyser un problème et écrire du bon code (dans le sens conforme, efficace, facile à mettre au point et à maintenir). Cela s'applique à la gestion de systèmes physiques en toute sécurité ou à des protocoles de communication, avec la même facilité.
Pour chaque état, un (ou des) évènements permettent une transition vers un autre état (ou d'autres états), en réalisant éventuellement une action déterminée. Il peut parfois y avoir retour vers le même état (à une variable d'état près, éventuellement). A chaque état peuvent être associées un jeu de valeurs des variables d'état (ce qui peu matérialiser en quoi consiste une 'transition', mais pas toujours).
Cette approche permet effectivement de réfléchir à bien poser le problème, à trouver les bons états, les bonnes variables d'état, à tester sur papier la conformité du fonctionnement aux attentes, tout cela avec rapidité (ce n'est finalement que du dessin servant de support à une 'expérience de pensée') mais avec une grande sûreté (l'automate dessiné fait ce que l'on veut, ou non, le constat est immédiat, et en cas de non, c'est que la modélisation est à revoir). Cette approche événementielle est en général vécue comme assez naturelle. Tout cela sans avoir écrit une seule ligne de code !
http://fadiese.hd.free.fr/barbadidoua/i ... nes-d-etat
là c'est clair et concis : il faut lire toute la page :)
Le programme va donc regarder dans quelle étape il se trouve (y positionner les actionneurs, c'est à dire agir sur l'environnement=écriture des sorties) puis voir (en observation l'environnement=lecture des entrées)s'il doit effectuer la transition vers l'étape suivante
Règles
http://pinballmakers.com/wiki/index.php/Rule_Flow
des exemples de règles à coder :
http://pinball.org/rules/devilsdare.txt
► exemples :
https://create.arduino.cc/proj…l-machin ... 3?f=1#code
Le code de Bob Blomquist est un bon début car plutôt simple :
- 1 seul arduino pour piloter le tout
- gestion d'une seule bille en jeu
Pendant ma lecture pour l'analyser, j'ai retravaillé le code (quelques bugs mineurs, découpage en fonctions, petite optimisation de la taille des variables, gestion des pins par un tableau et des boucles...). Ca se compile mais ce n'est pas testé

en particulier le recours aux pointeurs pour modifier les points selon les types de cible.
Code : Tout sélectionner
// January 24, 2016
// created by Bob Blomquist
// https://create.arduino.cc/projecthub/BobB/arduino-controlled-pinball-machine-525863?f=1
// pinball controlled by a single Arduino Mega 2560 board
// 8 targets, 3 roll overs, 4 pop bumpers, 1 pressure sensor to check if the ball has been lost
// 1 single ball management
// pop bumpers status is read through analog pin via a voltage divider
// 02-2018
// added comments, sliced into 4 sub procedures or function, changed variable types, pin numbers and status managed through arrays, speed up loop tweak by Mat13
// compiled OK but untested ?
const byte TxPin = 17;
long Score = 0;
long OldScore = 0;
byte Target_Points;
byte Pop_Points;
byte Roll_Points;
// target rollover alley popbumper
// array index: 0 - 7 8 - 10 11-12 13-16
byte switches_pin[17] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 15, 16, 20, 21, 22, 23};
// to determine when all have been hit and the value needs upgrading
// and the lights need turning off.
byte switches_status[17] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int Milli = 10;
int Flash = 100;
byte Sum = 0; //number of target < 255
byte Ball = 0; //number of ball < 255
byte Shot = 0; //number of shot < 255
boolean Lost = false;
int Tare_Pressure_Sensor = 1024;
#include <SoftwareSerial.h>
SoftwareSerial mySerial = SoftwareSerial(255, TxPin);
void reset_points_values()
{
Target_Points = 1;
Pop_Points = 1;
Roll_Points = 10;
}
void setup() {
// setupo the LCD serial interface and pin
pinMode(TxPin, OUTPUT);
digitalWrite(TxPin, HIGH);
mySerial.begin(9600);
mySerial.write(12); // Clear
mySerial.write(17); // Turn backlight on
//turn target pins into inputs
//If a pull-down resistor is used, the input pin will be LOW when the switch is open and HIGH when the switch is closed.
for (int i = 0; i < 13; i++) {
//rollover inputs
//lower ball shot switch
//upper ball shot switch
pinMode(switches_pin[i], INPUT_PULLUP);
//turn target light pins into output, respective
//ie ( target pin number + 30 ) = light pin number
//rollover lights, respective
//pop bumper lights, respective
pinMode(switches_pin[i] + 30, OUTPUT);
}
//pop bumper lights
pinMode(50, OUTPUT);
pinMode(51, OUTPUT);
pinMode(52, OUTPUT);
pinMode(53, OUTPUT);
reset_points_values();
}
void loop() {
while (1 == 1) //a tweak that creates a real time loop code without any arduino's framework delays
{
// put your main code here, to run repeatedly:
//check targets, roll over and pop bumpers
checkhits_light_score_mult(0, 7, &Target_Points, 2);
//scan all the targets inputs
//switch on the light of the hit target
//store the target status
//check the rule "if all targets have been hit, then multiply the value of one target"
// check Rollovers
checkhits_light_score_mult(8, 10, &Roll_Points, 5);
// check PopBumpers
checkhits_light_score_mult(13, 16, &Pop_Points, 10);
//increment ball number when ball hit lower alley switch or ball hit upper alley switch
if ( (digitalRead(15) == LOW) || (digitalRead(16) == LOW))
{ increase_ball_counter(); // increase ball counter and tare the pressure gauge
}
//test if ball is on the pressure pad
if (analogRead(7) > Tare_Pressure_Sensor) { //ball is on the pressure pad Shot = 0; if (Lost == false) { //mySerial.print(analogRead(7)); //Score = Score + 100; Lost = true; if (Ball >= 5) { //Game Over game_over(); } }
}
//print to LCD
print_score_and_ball_to_LCD();
}
}
void checkhits_light_score_mult(byte first, byte last, byte *points, byte multiplier)
{
// *points is a pointer: this will allow the procedure to modify the global value of Target_Points, Pop_Points, Roll_Points
//a loop to read all the switchs of the target
//to check if a target was hit
for (int i = first; i <= last; i++) {
switch (i) {
case 0 ... 12: //digital pins
if (digitalRead(switches_pin[i]) == LOW) {
//Target activated
switches_status[i] = 1; // status memorized outside the main loop (global variable)
//add target score to the score
Score = Score + *points;
//turn on Target light because target has been hit
digitalWrite(switches_pin[i] + 30, HIGH);
//delay so as not get multiple points for one hit
delay(Milli); //debounce
// slow the whole loop in case of target hit but the ball needs time to travel to the next target, so it's OK
break;
}
default: //analog pins used to read the pop bumper status through voltage diviser
if (analogRead(switches_pin[i]) > 500) {
//Target activated
switches_status[i] = 1; // status memorized outside the main loop (global variable)
//add target score to the score
Score = Score + *points;
//turn on Target light because target has been hit
digitalWrite(switches_pin[i] + 30, HIGH);
//delay so as not get multiple points for one hit
delay(Milli); //debounce
// slow the whole loop in case of target hit but the ball needs time to travel to the next target, so it's OK
break;
}
}
}
// count the number of targets that have been hit
byte Sum = 0;
byte maximum_hits = 0;
for (int i = first; i <= last; i++) {
Sum = Sum + switches_status[i];
maximum_hits++;
}
//compare number of targets hit versus maximum
if (Sum == maximum_hits) {
//all Targets are now lit
for (int j = 0; j < 3; j++) {
// so flash and then turn off 3 times (j loop)
for (int i = first; i <= last; i++) {
digitalWrite(switches_pin[i] + 30, LOW);
}
delay(Flash);
for (int i = first; i <= last; i++) {
digitalWrite(switches_pin[i] + 30, HIGH);
}
delay(Flash);
}
//reset the target to "not hit" status and switch off the light
for (int i = first; i <= last; i++) {
digitalWrite(switches_pin[i] + 30, LOW); // switch off the light
switches_status[i] = 0; // reset target status to 0
}
delay(Flash);
// Rule : if all targets have been hit, then enter X multiplier mode
//Multiply target value by the multiplier factor
*points = *points * multiplier;
}
}
void print_score_and_ball_to_LCD()
{
if (Score != OldScore) {
mySerial.write(12); // Clear
delay(5); // Required delay
//mySerial.print(analogRead(7));
// First line for the score
mySerial.print(Score);
mySerial.write(13); // Form feed
// Second line: # ball or game over
if (Lost == true) {
mySerial.print("Game Over!!!");
}
else {
mySerial.print("Ball = ");
mySerial.print(Ball);
}
// if OldScore was -1 because of increase_ball_counter procedure, reset the score as previous score
OldScore = Score;
}
}
void increase_ball_counter()
{
//if not already done so, increase Ball
if (Shot == 0) {
//Set Lost = false since not on pressure pad
Lost = false;
Tare_Pressure_Sensor = analogRead(7) + 20;
//set OldScore to force reprint ball value on LCD
OldScore = -1; //the LCD procedure will then refresh the print on LCD with new ball value
Ball = Ball + 1;
Shot = 1;
}
if (Ball > 5) {
// reset the value in order to start a new game
Ball = 1;
Score = 0;
//reset the score value of hits
reset_points_values();
}
}
void game_over()
{
//Flash Targets and target status reset to 0.
//flash and then turn off 3 times (j loop)
for (int j = 0; j < 3; j++) {
for (int i = 0; i <= 16; i++) {
digitalWrite(switches_pin[i] + 30, LOW);
}
delay(Flash);
for (int i = 0; i <= 16; i++) {
digitalWrite(switches_pin[i] + 30, HIGH);
}
delay(Flash);
for (int i = 0; i <= 16; i++) {
digitalWrite(switches_pin[i] + 30, LOW);
}
}
// reset target status to 0
for (int i = 0; i <= 16; i++) {
switches_status[i] = 0;
}
}
un autre exemple par Frogger1108
https://create.arduino.cc/proj…no-pinba ... ine-4a3314
plusieurs exemples simple ou compliqué :
howtobuildapinballmachine.wordpress.com ->
http://www.space-eight.com/Downloads.html
► des liens pour des projets Flipper arduinos :
une liste ici
https://pinside.com/pinball/forum/topic ... w-and-tell (pas de mise à jour depuis 2 ans)
https://retronics.wordpress.com/2015/07 ... h-arduino/ code arduino
https://github.com/retronics/aspen_logi ... _logic.ino
"Pinduino"
https://pinside.com/pinball/forum/topic ... in-pinhead : une carte pour repiquer les infos du flipper et ajouter des mods (éclairages...) en fonction des événements.
une idée pour chronométrer ses billes :
https://pinside.com/pinball/forum/topic ... your-balls
"l'ai-je vraiment gardée 5 minutes pleines ???" ça tombe bien j'ai le petit afficheur 8 chiffres qui ne me servait plus :pp