Skip to content

Instantly share code, notes, and snippets.

@MatteoRagni
Created August 30, 2015 15:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MatteoRagni/16778c57ae0b404991c2 to your computer and use it in GitHub Desktop.
Save MatteoRagni/16778c57ae0b404991c2 to your computer and use it in GitHub Desktop.
Arduino per la didattica. Sorgenti da completare
#include <Servo.h>
Servo servo;
#define SERVO_MIN 5
#define SERVO_MAX 175
#define STEP_SIZE 1
// Definizione della interfaccia:
#define SERIAL_LASER_ON 'l'
#define SERIAL_LIGHTS_ON 'd'
#define SERIAL_NEXT_STEP 'n'
#define SERIAL_PREV_STEP 'p'
#define SERIAL_GO_HOME 'h'
#define SERIAL_GO_TO 'g'
#define SERIAL_QUERY '?'
#define SERIAL_WAIT 'w'
#define PRINT_PROMPT() Serial.print('>');
#define SERVO_PIN 9
#define LIGHTS_PIN 3
#define LASER_PIN 5
enum StateID {
WAIT,
LASER,
LIGHTS,
SERVO
};
struct State {
StateID id;
StateID transition;
int x_position;
int u_position;
bool laser;
bool lights;
};
struct State state;
// Tools ////////////////////////////////////////////////////
/* SERVO */
void servo_exec() {
if (state.id == SERVO) {
if (state.x_position != state.u_position) {
int dir = (state.x_position < state.u_position ? 1 : -1);
state.x_position += dir;
if (state.x_position >= SERVO_MIN && state.x_position <= SERVO_MAX) {
servo.write(state.x_position);
} else {
state.transition = WAIT;
}
} else {
state.transition = WAIT;
}
}
}
void servo_go_to(int new_pos) {
if (new_pos >= SERVO_MIN && new_pos <= SERVO_MAX) {
state.u_position = new_pos;
state.transition = SERVO;
}
}
void servo_go_next() {
servo_go_to(state.x_position + STEP_SIZE);
}
void servo_go_prev() {
servo_go_to(state.x_position - STEP_SIZE);
}
void servo_go_home() {
servo_go_to(SERVO_MIN);
}
void servo_sync() {
state.u_position = state.x_position;
}
/* LASER */
void laser_switch() {
state.laser = (state.laser ? false : true);
digitalWrite(LASER_PIN, (state.laser ? HIGH : LOW));
}
void laser_on() {
if(!state.laser)
laser_switch();
}
void laser_off() {
if(state.laser)
laser_switch();
}
/* LIGHTS */
void lights_switch() {
state.lights = (state.lights ? false : true);
analogWrite(LIGHTS_PIN, (state.lights ? 255 : 0));
}
void lights_on() {
if(!state.lights)
lights_switch();
}
void lights_off() {
if(state.lights)
lights_switch();
}
// Setup ///////////////////////////////////////////////////////////
void setup() {
// Initializzare lo stato in modo consistente
// Laser
pinMode(LASER_PIN, OUTPUT);
laser_off();
delay(10);
// Luci
lights_off();
delay(10);
// Servo
servo.attach(SERVO_PIN);
servo.write(SERVO_MIN);
delay(250);
state.id = WAIT;
state.transition = WAIT;
state.x_position = SERVO_MIN;
state.u_position = SERVO_MIN;
Serial.begin(115200);
}
/*******************************************************************/
/* */
/* COMPLETARE LE SEZIONI SOTTOSTANTI! */
/* */
/*******************************************************************/
// State Machine Handling //////////////////////////////////////////
void state_on_enter() {
if (state.id != state.transition) {
switch(state.transition) {
case WAIT:
break;
case LASER:
break;
case LIGHTS:
break;
case SERVO:
break;
default:
break;
}
state.id = state.transition;
}
}
void state_on_exec() {
switch(state.id) {
case WAIT:
break;
case LASER:
break;
case LIGHTS:
break;
case SERVO:
break;
default:
break;
}
}
void state_on_exit() {
if (state.id != state.transition) {
switch(state.id) {
case WAIT:
// void
break;
case LASER:
break;
case LIGHTS:
break;
case SERVO:
break;
default:
break;
}
}
}
// Main Loop ///////////////////////////////////////////////////////////
int buff = 0;
void loop() {
if(Serial.available()) {
char ch = Serial.read();
switch(ch) {
case '0'...'9':
break;
case SERIAL_LASER_ON:
break;
case SERIAL_LIGHTS_ON:
break;
case SERIAL_NEXT_STEP:
break;
case SERIAL_PREV_STEP:
break;
case SERIAL_GO_HOME:
break;
case SERIAL_GO_TO:
break;
case SERIAL_QUERY:
break;
case SERIAL_WAIT:
break;
default:
break;
}
PRINT_PROMPT();
}
state_on_exit();
state_on_enter();
state_on_exec();
delay(5);
}
/* La didattica con Arduino
* Matteo Ragni
* Universita' degli Studi di Trento
*
* Obbiettivi:
* Costruire una piccola macchina a stati. La macchina comanda un fading led e un puntatore
* laser. Il laser non deve essere mai acceso quando il led e' acceso. Il fader deve sempre
* ripartire da zero quando richiamato.
*
*
* +----------------+
* | Àrduino |
* | UNO | +---------------+
* | Pin 5 --------------+ LASER +-----+
* | | +---------------+ |
* | | |
* | Pin 3 (~) -----+ |
* | | | +--------+ +---------+ |
* | | +---+ 220omh +--+ LED +----+
* | | | +--------+ +---------+ |
* | | | +--------+ +---------+ |
* | | +---- 220omh +--+ LED +----+
* | | | +--------+ +---------+ |
* | GND | | +--------+ +---------+ |
* +------|---------+ +---+ 220omh +--+ LED +----+
* | +--------+ +---------+ |
* | |
* | |
* +---------------------------------------------+
*/
/* Struttura della macchina a stati
* +---------------+ Serial 'n'
* | |<----------------+---------------------------------------+
* | Stato NULLO | Serial 'd' | |
* | 0|--+-----------+ | |
* +---------------+ | | | |
* | | V | |
* Serial | | +---------------+ |
* 'l' | | | | |
* | | +-| Init LED PWM | |
* V | | | 2| |
* +---------------+ | | +---------------+ |
* | |--+ | | end init |
* +-| Exec LASER | | | |
* | | 1|<------+ | +-------------------------+-----------+
* | +---------------+ Serial V | | |
* | ^ 'l' +---------------+ pwm = 255 +---------------+ |
* | | | Exec LED PWM |---------->| Exec LED PWM | |
* | | | pwm_dir = 1 | | pwm_dir = -1 | |
* | | | 3|<----------| 4| |
* | | +---------------+ pwm = 0 +---------------+ |
* | | Serial 'l' | | |
* | +-------------------------+---------------------------+ |
* +---------------------------------------------------------------------------+
*/
// Struttura che contiene tutte le informazioni riguardanti lo
// stato del nostro automa
struct State {
// Id dello stato corrente della macchina
int id;
// Id dello stato nel quale si deve effettuare la transizione
int transition;
// Stato della componente A
int pwm_value;
int pwm_direction;
// Stato della componente B
int laser;
};
struct State state;
#define A_PIN 3
#define B_PIN 5
void setup() {
Serial.begin(115200);
pinMode(B_PIN,OUTPUT);
// Inizializzazione dello stato della macchina
// attenzione: deve essere consistente...
state.id = 0;
state.pwm_value = 0;
state.pwm_direction = 0;
state.laser = LOW;
analogWrite(A_PIN, 0);
}
/////////////////////////////////////////////////////////////////////////////////////
// Funzioni Led
void led_init() {
state.pwm_value = 0;
state.pwm_direction = 1;
analogWrite(A_PIN, state.pwm_value);
state.transition = 3;
}
void led_fadein_in() {
state.pwm_direction = 1;
}
void led_fadein_loop() {
state.pwm_value += (5 * state.pwm_direction);
if (state.pwm_value > 255) {
state.transition = 4;
} else {
analogWrite(A_PIN, state.pwm_value);
}
}
void led_fadein_exit() {
if (state.transition != 4)
analogWrite(A_PIN, 0);
}
void led_fadeout_in() {
state.pwm_direction = -1;
}
void led_fadeout_loop() {
state.pwm_value += (5 * state.pwm_direction);
if (state.pwm_value < 0) {
state.transition = 3;
} else {
analogWrite(A_PIN, state.pwm_value);
}
}
void led_fadeout_exit() {
if (state.transition != 3)
analogWrite(A_PIN, 0);
}
// Funzioni Laser
void laser_off() {
state.laser = LOW;
digitalWrite(B_PIN, state.laser);
}
void laser_on() {
state.laser = HIGH;
digitalWrite(B_PIN, state.laser);
}
/*******************************************************************/
/* */
/* COMPLETARE LE SEZIONI SOTTOSTANTI! */
/* */
/*******************************************************************/
//////////////////////////////////////////////////////////////////////////////////////
// Macchina a stati: esecuzione in ingresso in uno stato
void state_on_enter() {
if(state.transition != state.id) {
switch(state.transition) {
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
default:
break;
}
#ifdef DEBUG
Serial.print("Switch from: ");
Serial.print(state.id);
Serial.print(" to:");
Serial.println(state.transition);
delay(10);
#endif
state.id = state.transition;
}
}
// Macchina a stati: esecuzione nello stato
void state_on_exec() {
switch(state.id) {
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
default:
break;
}
}
// Macchina a stati: Esecuzione in uscita da uno stato
void state_on_exit() {
if(state.transition != state.id) {
switch(state.id) {
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
default:
break;
}
}
}
/*******************************************************************/
/* */
/* COMPLETARE LE SEZIONI SOVRASTANTI! */
/* */
/*******************************************************************/
void loop() {
if (Serial.available()) {
char ch = Serial.read();
switch(ch) {
case 'l':
state.transition = 1;
break;
case 'd':
state.transition = 2;
break;
case 'n':
state.transition = 0;
break;
case '?':
Serial.print(state.id);
Serial.print('\t');
Serial.print(state.pwm_value);
Serial.print('\t');
Serial.print(state.pwm_direction);
Serial.print('\t');
Serial.print(state.laser);
Serial.print('\n');
break;
default:
break;
}
}
state_on_exit();
state_on_enter();
state_on_exec();
delay(20);
}
/* La didattica con Arduino
* Matteo Ragni
* Universita' degli Studi di Trento
*
* Obbiettivi:
* Comandare un servo utilizzando Arduino. Il modulo deve essere in grado
* di ricvevere un angolo in input via seriale (lightweight arduino parser)
* effettuare lo spostamento aventi o indietro di uno step, ritornare a casa
* etc.
* Il progetto pone le basi su come costruire in modo efficiente una interfaccia
* macchina macchina via seriale.
*
* +--------------+
* | Arduino |
* | UNO | +--------+
* | | +--------+
* | | +--------++
* | | | ||
* | Pin 9 (~PWM) +--------------+ Giallo ||
* | 5V +--------------+ Rosso ||
* | GND +--------------+ Nero ||
* | | +--------++
* | | ServoMotore
* +--------------+
*/
#include <Servo.h>
Servo servo;
// Riduciamo il campo di spostamento de 5 a 175 gradi per
// non stallare il motore. Il problema di stallaggio deriva dalla
// non ottima costruzione del servo
#define START_ANGLE 5
#define STOP_ANGLE 180
// Scriviamo una piccola funzione che stampa in seriale il valore attuale di
// angolo a cui ci troviamo.
#define REPORT_ANGLE() Serial.print(pos);
// Il prompt e' un carattere che ci permette di capire dal
// computer che il nostro spostamento e' terminato.
#define RETURN_PROMPT() Serial.print('|');
// Le tre variabili globali utilizzate nello sketch. pos trattiene lo stato attuale
// del servo (ovvero la sua posizione
int pos = START_ANGLE;
int buff = 0;
////////////////////////////////////////////////////////////////////////
void move_servo_at(int buff) {
if (buff >= START_ANGLE && buff <= STOP_ANGLE) {
pos = buff;
} else {
pos = (buff < START_ANGLE ? pos = START_ANGLE : pos = STOP_ANGLE);
}
REPORT_ANGLE();
servo.write(pos);
}
void move_servo_next() {
if (pos < STOP_ANGLE) {
pos += 1;
REPORT_ANGLE();
servo.write(pos);
}
}
void move_servo_previous() {
if (pos > START_ANGLE) {
pos -= 1;
REPORT_ANGLE();
servo.write(pos);
}
}
void move_servo_at_home() {
pos = START_ANGLE;
REPORT_ANGLE();
servo.write(pos);
}
////////////////////////////////////////////////////////////////////////
void setup()
{
servo.attach(9);
servo.write(pos);
Serial.begin(115200);
}
/*******************************************************************/
/* */
/* COMPLETARE LE SEZIONI SOVRASTANTI! */
/* */
/*******************************************************************/
void loop()
{
char ch;
if (Serial.available()) {
ch = Serial.read();
switch(ch) {
case '0'...'9':
buff = buff * 10 + (ch - '0');
break;
case 'g':
RETURN_PROMPT();
break;
case 'h':
RETURN_PROMPT();
break;
case 'n':
RETURN_PROMPT();
break;
case 'p':
RETURN_PROMPT();
break;
default:
buff = 0;
RETURN_PROMPT();
break;
}
}
delay(20);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment