Go Down

Topic: Aiuto per un vecchio appassionato (Read 3846 times) previous topic - next topic

ArTex

Ciao a tutti,

sono un'appassionato e ogni tanto mi diletto con il modellismo e anche con dei semplici (ebbenesì) copia incolla per fare dei giochini con i miei bambini...

Ora volevo fare qualcosa di diverso ma sono un pò di giorni che mi sono arenato e Vi chiedo cortesemente un' aiuto perchè non sò come fare...

Per Natale volevo fare con un trenino un tracciato ovale semplice semplice e dare un tempo di riposo in galleria al treno facendolo passare su un reed, e dopo alcuni min farlo ripartire...

Ma non riesco a farlo da solo.

Grazie a chi mi aiuterà, Marco.

Patrick_M

mmmm ho dato un'occhiata veloce al programma.
Quando arrivi in galleria e lo switch o chi per esso viene attivato devi fermare il treno e cominciare a contare il tempo che passa.... passato il tempo previsto far ripartire il treno.
quindi ti serve usare il "fatidico" millis() !

Per capire come funziona e come applicare la funzione millis(), puoi studiare prima QUI, poi QUI ed infine leggere anche QUI e QUI  e questo post di Claudio_FF... vedrai che ti sarà tutto più chiaro
per inserire (lo sketch) il programma, dall'IDE clicca modifica, clicca copia per il forum poi vieni qui e incolla nel tuo post (ctrl+v) ;)

ArTex

Grazie Patrick,

ma leggendo e rileggendo il forum, non posso fare da me, cercherò qualcuno che magari sotto compenso mi possa realizzare la cosa.

Ci rinuncio non riesco a ricordarmi più nulla, non voglio fare pena a nessuno, ma è la verità, non posso chiedere un aiuto se non mi ricordo più come si usa.

Ritorno alle mie cose quando mi serviranno copia e incolla e pazienza.

Grazie e buon divertimento a tutti, Marco.

torn24

Un uso di millis() per attendere 3 minuti di treno fermo.

Se hai bisogno di arrestare il treno o farlo ripartire in altre parti del programma, devi mettere stato=0 IL TRENO PARTE, stato=1 IL TRENO SI FERMA.


Code: [Select]



// descrizione: Partenza Treno, si spegne la croce di S.andrea, il treno rientra in galleria preme un contatto e si interrompe la corsa al treno,
//si riaccende la Croce di S.Andrea e dopo 3 min riparte il treno




const int  BUTTON = 2;    // pin di input a cui è collegato il pulsante
const int LED_A = 13;       // led A croce di S.Andrea
const int LED_B = 11;       // led B croce di S.Andrea
const int TRENO = 10;       // Treno collegato al pin digitale 13
// Variabili globali (tutti interi)
int statoButton     = 0;      // stato del pulsante (inizialmente non premuto)
int lastStatoButton = 0;      // ultimo stato del pulsante (per ora non premuto)
int countButton     = 0;      // Conteggio del bottone

unsigned long tempo=0;
byte stato=0; // Se stato vale zero il treno funziona, se stato vale 1 il treno si ferma

// Avvio dell'applicazione


void setup()
{
  pinMode(LED_A, OUTPUT);       // imposta il pin digitale come output
  pinMode(LED_B, OUTPUT);
  pinMode(TRENO, OUTPUT);
  pinMode(BUTTON, INPUT);     // imposta il pin digitale come input
}

// Avvio del loop
void loop()
{

  // Verifico se l'utente ha premuto il bottone ???
  if(digitalRead(BUTTON))
  {
    // Aspetto 15ms per far alzare il dito all'utente
    delay(15);
    // Cambio l'ultimo stato del bottone
    if(lastStatoButton==0) lastStatoButton=1;
    else lastStatoButton=0;
    // Aumento il count del bottone
    if(countButton<=3) countButton=countButton+1;
    else countButton=0;
  }

  // In base allo stato del bottone scelgo l'azione del led
  switch (countButton)
  {
    // Led lampeggia ogni mezzo secondo
  case 1:
    digitalWrite(LED_A, HIGH);  // accende il LED
    delay(500);              // aspetta un secondo
    digitalWrite(LED_B, LOW);   // spegne il LED
    delay(500);              // aspetta un secondo
     digitalWrite(LED_B, HIGH);  // accende il LED
    delay(500);              // aspetta un secondo
    digitalWrite(LED_A, LOW);   // spegne il LED
    stato=1; // Ferma il treno
tempo=millis(); // Inizia il conteggio
     
    break;
// quando il treno arriva in galleria c'è lo switch o tasto ma la funzione dovrebbe portarmi il riavvio dell loop come faccio???
  }
  if(stato){// Ferma il treno se stato vale 1
 
      digitalWrite(LED_A, LOW);
      digitalWrite(LED_B, LOW);
      digitalWrite(TRENO, LOW);
 
  }else{
 
  digitalWrite(TRENO, HIGH); // Se stato vale 0 il treno è in moto
  }
 
  if(stato==1 && millis()-tempo >= (3*60*1000)){
  /* Se stato è uguale a uno e sono passati
     tre minuti, mette stato a zero e quindi accende il treno */
       stato=0;
  }
}






Datman

#4
Nov 27, 2018, 03:55 pm Last Edit: Nov 27, 2018, 08:42 pm by Datman
Ciao, Marco.
Perché conti il numero di pressioni del pulsante? Vedo che poi metti solo un case 1... Che cosa vuoi fare?
Per quello che ho capito, farei così:
Code: [Select]

// Descrizione: Partenza Treno, si spegne la croce di S.andrea, il treno rientra in galleria,
// preme un contatto e si interrompe la corsa al treno,
// si riaccende la Croce di S.Andrea e dopo 3 min. riparte il treno.

const int  BUTTON = 8;   // pin di input a cui è collegato il pulsante
const int LED_A = 13;     // led A croce di S.Andrea
                                  // N.B.: Il pin 13 lampeggia all'accensione per la presenza del bootloader.
const int LED_B = 11;     // led B croce di S.Andrea
const int TRENO = 10;    // Treno collegato al pin digitale 10

// Variabili globali (tutti interi)
byte statoButton     = 0;  // stato del pulsante (inizialmente non premuto)
byte lastStatoButton = 0; // ultimo stato del pulsante (per ora non premuto)
byte countButton     = 0;  // Conteggio del bottone
byte lastCountButton = 0;
unsigned long t1; // millis() per i 3 minuti di attesa.

void(* Riavvia)(void)=0; // Dove scriverai "Riavvia();" verrà riavviato il loop.

void setup()
{
pinMode(0,OUTPUT); // Segmento A di un display ad anodo comune via 1,5kOhm circa.
pinMode(1,OUTPUT); // Segmento B di un display ad anodo comune via 1,5kOhm circa.
pinMode(2,OUTPUT); // Segmento C di un display ad anodo comune via 1,5kOhm circa.
pinMode(3,OUTPUT); // Segmento D di un display ad anodo comune via 1,5kOhm circa.
pinMode(4,OUTPUT); // Segmento E di un display ad anodo comune via 1,5kOhm circa.
pinMode(5,OUTPUT); // Segmento F di un display ad anodo comune via 1,5kOhm circa.
pinMode(6,OUTPUT); // Segmento G di un display ad anodo comune via 1,5kOhm circa.
pinMode(7,OUTPUT); // Punto  (.) di un display ad anodo comune via 1,5kOhm circa.
 
pinMode(LED_A, OUTPUT);
pinMode(LED_B, OUTPUT);
pinMode(TRENO, OUTPUT);
pinMode(BUTTON, INPUT);
pinMode(BUTTON, INPUT_PULLUP); // Resistenza di pullup interna per mettere il pulsante verso massa.
                               // Il pulsante verso massa è anche comodo perché non devi portare fuori il +V.
}                              // Mettere un condensatore da 10uF tra il pin di ingresso e massa come antirimbalzo.

void loop()
{
if(lastStatoButton==1 && !digitalRead(BUTTON)) // Se il pulsante non era premuto e adesso è premuto (chiude a massa)
  {
    lastStatoButton=0;  // 0 = premuto
    if(countButton<=3) countButton+=1; // Fino a 3 incrementa di uno.
    else countButton=0;
  }
if(digitalRead(BUTTON)==1) lastStatoButton=1; // Se il pulsante viene lasciato, ne prende nota.

// In base allo stato del bottone scelgo l'azione del led
switch(countButton)
  {
  case 1: // Se il pulsante è stato premuto 1 volta:
    {
    if(countButton==1 && lastCountButton!=1) // Se è diventato 1 adesso
      {
      lastCountButton=1;
      //      .gfedcba
      PORTD=0b11111001; // Visualizza "1" sul display.
      t1=millis(); // Si segna il tempo in t1.   
      } 
    if(millis()-t1<180000)
      {   // Fa lampeggiare i LED A e B in base al resto di millis() diviso 2000:
      if(millis()%2000<1000) {digitalWrite(LED_B, LOW); digitalWrite(LED_A, HIGH);} // spegne il LED B e accende il LED A.
      else                   {digitalWrite(LED_A, LOW); digitalWrite(LED_B, HIGH);} // spegne il LED A e accende il LED B.
      }
    else
      {
      digitalWrite(LED_A, LOW);
      digitalWrite(LED_B, LOW);
      digitalWrite(TRENO, HIGH); // dopo 3 min parte il treno.
       }
    } // END case 1
  case 2:
    {
    if(countButton==2 && lastCountButton!=2) // Se è diventato 2 adesso
      {
      lastCountButton=2;
      //      .gfedcba
      PORTD=0b10100100; // Visualizza "2" sul display.
      // ... ... ...
      }
    } // END case 2
  case 3:
    {
    if(countButton==3 && lastCountButton!=3) // Se è diventato 3 adesso
      {
      lastCountButton=3;
      //      .gfedcba
      PORTD=0b10110000; // Visualizza "3" sul display.
      // ... ... ...
      }
    }  // END case 3
  case 4:
    {
    if(countButton==4 && lastCountButton!=4) // Se è diventato 4 adesso
      {
      lastCountButton=4;
      //      .gfedcba
      PORTD=0b10101100; // Visualizza "4" sul display.
      // ... ... ...
      }
    }  // END case 4
  } // END switch
             
  // quando il treno arriva in galleria c'è lo switch o tasto ma la funzione dovrebbe portarmi il riavvio dell loop come faccio???
  // Vedi quanto scritto poco prima del setup().

} // END loop()

Ho previsto anche un display a 7 segmenti ad anodo comune per indicare lo stato delle pressioni del pulsante (1...4).
Hi,I'm Gianluca from Roma.I play&work with electronics since I was16(1984).
After 25yrs of maintenance on cameras&video mixers,since 2013myJob is HDTVstudios design.
Since Jan2015 IPlayWith Arduino:bit.ly/2F3LPWP
Thanks 4 a Karma if U like my answer

ArTex

#5
Nov 27, 2018, 11:09 pm Last Edit: Nov 27, 2018, 11:11 pm by ArTex
Buona sera,

dopo un pò di prove fatte in modo empirico e guardando altre prove che avevo fatto sono riuscito a far lampeggiare correttamente la Croce di S.Andrea ma non a far funzionare lo sketch nel modo che mi serviva... A questo punto provo a sforzarmi un pò di più. Tra un cliente e un' altro però se entro il giorno che dovrò montare la vetrina vi dovrò rompere ancora.

Il treno non parte da solo dopo 3 min, e se modifico i valori avvio arduino, parte il treno lampeggia la croce di S.Andrea e non si ferma più.

Giuro metto in vetrina Grazie Forum Arduino! E posto la foto.

Grazie Datman ma per me è arabo ciò che hai scritto, troppo diffcile... Mi sono diplomato come peritomeccanico nel '98 al serale... Mi ricordo a malapena il quadrato di un binomio...

Grazie Mille torn24 dell'aiuto non sperato, Marco.

Datman

#6
Nov 27, 2018, 11:23 pm Last Edit: Nov 27, 2018, 11:30 pm by Datman
Che cosa è troppo difficile?... Il display è in più. Se non lo monti, il resto funziona ugualmente. :)

Il pulsante, anziché tra l'ingresso e il positivo, devi metterlo tra l'ingresso e massa. D'altra parte, se metti il pulsante verso il positivo devi mettere una resistenza esterna verso massa. Mettendo il pulsante che chiude a massa, invece, usiamo la resistenza già disponibile dentro al microcontrollore atmega328p.

Per risolvere il problema dei rimbalzi del pulsante, prendi un comune condensatore elettrolitico da circa 10 microfarad 16 volt (o 25 volt o 50 volt o quello che è) e lo colleghi tra l'ingresso e massa, in parallelo al pulsante, con il + sull'ingresso e il - a massa.
Hi,I'm Gianluca from Roma.I play&work with electronics since I was16(1984).
After 25yrs of maintenance on cameras&video mixers,since 2013myJob is HDTVstudios design.
Since Jan2015 IPlayWith Arduino:bit.ly/2F3LPWP
Thanks 4 a Karma if U like my answer

ArTex

Scusami,

ma sono andato in crisi dopo che ho visto il codice così complicato... In realtà il pulsante lo cambierò con un reed magnetico, perchè sotto la locomotiva ci metterò un magnete.

Ora mi faccio coraggio  :o Marco.

torn24

#8
Nov 28, 2018, 07:22 am Last Edit: Nov 28, 2018, 07:33 am by torn24
Quote
Che cosa è troppo difficile?.
Datman Non sono critiche solo un osservazione!

L'idea di arduino è rendere semplice o meglio più semplice l'uso di un microcontrollore!
Per cui nel linguaggio semplificato di arduino non si usano registri, porte, puntatori a funzione e valori binari di bit :)
Mentre nel tuo codice ne fai uso, programmare un altro microcontrollore in questo modo è la norma, ma
l'idea di arduino era di avere un astrazione da questo modo di programmare :)

Per cui un utente medio di arduino non capisce il codice e quindi lo trova difficile :)

Domanda un puntatore a funzione inizializzato a zero equivale a chiamare la funzione loop()?
Forse basta un return, esce dalla funzione che poi verrà richiamata e ricomincerà .

torn24

ArTex se il treno non deve ripartire da solo non ti serve millis() che conta la pausa, però ti potrebbe servire per altri scopi.

gpb01

#10
Nov 28, 2018, 07:39 am Last Edit: Nov 28, 2018, 08:01 am by gpb01
Domanda un puntatore a funzione inizializzato a zero equivale a chiamare la funzione loop()?
Io invece faccio una critica a "dataman" (... e, se non vado errato, non è la prima volta), che utilizza, nei sui codici, cose "da non fare", come questa di usare un puntatore a zero per fare un "reset" software (... e quindi far ripartire TUTTO, non solo il loop()) che è ovunque sconsigliata (... è una cosa fatta a metà, in cui la MCU fa un salto alla locazione zero, ma l'hardware non viene reinizializzato come in un vero reset o un attivazione del watchdog).

Se si vuole far ripartire il loop(), come giustamente dice "torn24", basta una banale "return" dato che loop() è semplicemente una funzione continuamente richiamata dentro un ciclo FOR ... con "return" si esce ed il cliclo FOR la riattiva dall'inizio.

Guglielmo

P.S.: per inciso, anche setup() è una semplice funzione che, occorrendo, si può richiamare da dove si vuole ...
Search is Your friend ... or I am Your enemy !

Datman

Ciao, Guglielmo
Il riavvio l'ho usato una sola volta nei miei progetti per ricominciare il loop dopo aver fatto delle impostazioni. Sicuramente, però, sarebbe stato sufficiente impostare diversamente la struttura del programma.
Forse non l'ho neanche chiesto qui, ma l'ho trovato già trattato in inglese. Essendo stato chiesto esplicitamente senza ulteriori spiegazioni ed essendo molto semplice, l'ho riportato, senza pensare che quasi sicuramente non ne avrebbe avuto realmente bisogno.
Hi,I'm Gianluca from Roma.I play&work with electronics since I was16(1984).
After 25yrs of maintenance on cameras&video mixers,since 2013myJob is HDTVstudios design.
Since Jan2015 IPlayWith Arduino:bit.ly/2F3LPWP
Thanks 4 a Karma if U like my answer

gpb01

#12
Nov 28, 2018, 08:21 am Last Edit: Nov 28, 2018, 08:21 am by gpb01
... Forse non l'ho neanche chiesto qui, ma l'ho trovato già trattato in inglese. ...
... dai retta, butta via la discussione dove l'hai trovato :D :D :D

Guglielmo
Search is Your friend ... or I am Your enemy !

Datman

#13
Nov 28, 2018, 08:26 am Last Edit: Nov 28, 2018, 08:28 am by Datman
Ciao, torn24
Anch'io ho iniziato a programmare Arduino con tutte le sue funzioni "astrattive" ma, ben presto, mi sono reso conto delle limitazioni e delle complicazioni che portavano, ad esempio non contemporaneità delle commutazioni dei bit di una porta, dover scrivere 8 righe anziché una sola con un byte binario (senza essere più comprensibili nel pilotaggio di 7 segmenti, anzi viceversa), rallentamento del loop, senza contare cose che vanno fatte necessariamente a un livello più basso. A quel punto, da tecnico elettronico che sono da oltre trent'anni, non mi sono più concentrato sulla portabilità ma sull'ottimizzazione per ottenere il massimo che può offrire questa tecnologia. D'altra parte penso che, dati i costi non esorbitanti, se qualcuno vuole costruire qualcosa non sia fortemente limitato dalla scheda in suo possesso. Considera anche che io uso Arduino uno solo per fare qualche prova iniziale, ma poi monto l'atmega328p su millefori con ciò che serve.
Hi,I'm Gianluca from Roma.I play&work with electronics since I was16(1984).
After 25yrs of maintenance on cameras&video mixers,since 2013myJob is HDTVstudios design.
Since Jan2015 IPlayWith Arduino:bit.ly/2F3LPWP
Thanks 4 a Karma if U like my answer

gpb01

#14
Nov 28, 2018, 08:37 am Last Edit: Nov 28, 2018, 08:38 am by gpb01
... A quel punto, da tecnico elettronico che sono da oltre trent'anni, non mi sono più concentrato sulla portabilità ma sull'ottimizzazione per ottenere il massimo che può offrire questa tecnologia. ...
Tutto esatto, ma ... dimentichi che qui il 90% degli utenti NON è né un esperto di elettronica, né di programmazione di MCU e che quindi, la cosa più semplice per loro e più chiara da capire ed apprendere, è usare il framework "wiring" (...con tutti i suoi appesantimenti e rallentamenti).

Quindi, sempre meglio proporre soluzioni "classiche", comprensibili appunto anche da quel 90% dei lettori :)

Se poi c'è quello esperto che deisidera ottimizzare ed approfondire ... chiede ;)

Guglielmo
Search is Your friend ... or I am Your enemy !

Go Up