Accensione 7 relè con 7 pulsanti più 1 che spegne tutti

Buongiorno vorrei chiedere una cortesia a voi esperti, sto iniziando da pochissimo questa nuova esperienza di programmazione , dove trovo che sia veramente affascinante quanto complesso.
so che si inizia dall'accensione di un led ecc, ma ho la necessita di far accendere 7 relè da 7 pulsanti e spengerli dagli stessi, e poi con un pulsante separato avere la possibilità di spegnere tutti i relè
facendo delle ricerche ho trovato questo codice che può andar bene però provo ad aggiungere gli altri ingressi e altre uscite e mi crea sempre errori non so come proseguire avreste cortesemente modo di aiutarmi?
saluti
Emanuele
p.s se possibile vorrei inserire nei pulsanti un leggero ritardo :ovvero se premo il primo pulsante devo tenerlo premuto per qualche microsecondo prima che dia il consenso al relè in modo che non vi siano impurità nel segnale poichè comanderò tutto con una scheda touch da 16 canali utilizzandone solo 8 ovviamente comprendo che anche questa parte per me sia troppo difficile e se non è il caso non la considero.
esempio code

// Esempio 04: antirimbalzo2 - accendi il led appena è premuto il pulsante mantenendolo acceso quando si rilascia
// premendo una seconda volta il pulsante spegne il led
#define LED 13                // LED collegato al pin digitale 13
#define BUTTON 7              // pin di input dove è collegato il pulsante
int val = 0;                  // si userà val per conservare lo stato del pin di input
int vecchio_val = 0;          // si userà vecchio_val per conservare lo stato del pin di input al passo precedente
int stato = 0;                // ricorda lo stato in cui si trova il led, stato = 0 led spento, stato = 1 led acceso

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

void loop() {
  val = digitalRead(BUTTON);  // legge il valore dell'input e lo conserva

  // controlla se è accaduto qualcosa
  if ((val == HIGH) && (vecchio_val == LOW)){
    stato = 1 - stato;
    delay(15);                // attesa di 15 millisecondi
  } 

  vecchio_val = val;            // ricordiamo il valore precedente di val

    if (stato == 1) {
    digitalWrite(LED, HIGH);   // accende il led
  } 
  else {
    digitalWrite(LED, LOW);    //spegne il led
  }
}

Buongiorno e benvenuto nella sezione Italiana del forum,

:warning: prima di tutto ti segnalo che, nella sezione in lingua Inglese, si può scrivere SOLO in Inglese ... quindi, per favore, la prossima volta presta più attenzione in quale sezione metti i tuoi post; questa volta esso è stato spostato, da un moderatore della sezione di lingua Inglese, nella sezione di lingua Italiana ... la prossima volta potrebbe venire direttamente eliminato, dopo di che ...

... cortesemente, leggi attentamente il REGOLAMENTO di detta sezione, (prestando molta attenzione al punto 15) e poi, come da suddetto regolamento, fai la tua presentazione NELL'APPOSITA DISCUSSIONE spiegando bene quali esperienze hai in elettronica e programmazione, affinché noi possiamo conoscere la tua esperienza ed esprimerci con termini adeguati.

Grazie,

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell’apposita discussione, nel rispetto del succitato regolamento nessuno ti risponderà (eventuali risposte verrebbero temporaneamente nascoste), quindi ti consiglio di farla al più presto. :wink:

buongiorno ,mi scuso per aver sbagliato sezione ma inizialmente avevo messo il post in generale e pensavo di aver sbagliato dopo ho corretto in programmazione ma è andato in automatico in inglese dunque non ero al corrente del problema.

per favore potreste farmi un esempio su come aggiungere altri led e altri pulsanti al codice

Hai letto cosa ho scritto ?

Guglielmo

Allora devi affrontare un paio di problemi ...

  1. NESSUN pin di Arduino utilizzato come ingresso può essere lasciato "flottante" perché poi, il valore dato dalla digitalRead(), è casuale (i pin in input sono ad altissima impedenza e risentono di qualsiasi disturbo). Ogni pin in ingresso deve esssere condizionato ad un valore fisso (es. HIGH) e, alla pressione di un pulsante, portato alla condizione opport (es. LOW). Il modo più semplice è attivare le resistenze di pull-up interne dichiarano i vari pin come: pinMode(numeroPin, INPUT_PULLUP); ... in questo modo il pin sarà tenuto HIGH dalla resistenza di pull-up interna ed il tuo bottone, quando premuto, dovrà chiudere il pin verso GND.

  2. il debouncing ... nessun pulsante reale si comporta come un pulsante ideale. Un pulsante ideale quando lo premi si chiude e quado lo lasci si apre ... quelllo reale, causa i rimbalzi meccanici del contatti, alla pressione da una serie di chisure ed aperture e idem al rilascio:

switch-bounce-black-panel-mount

Il debouncing lo puoi sia fare da software (complicado il software con l'aggiunta di ritradi) sia da hardware (soluzione consigliata). Via hardware si può semplicemente fare con una resistenza ed un condensatore sull'ingresso:

Nel caso di pin con pull-up interna va bene il primo dei tre schemi.

Per il resto, la logica di memorizzare lo stato precedente e verificare se è cambiato è corretta (sempre se si fa bene il debouncing) così da distinguere la pressione ed il rilascio e quindi commutare la relativa uscita.

Buon lavoro :slight_smile:

Guglielmo

grazie Guglielmo,
io sto utilizzando come pulsante una scheda touch da 16 canali dove la sua uscita da direttamente +5v dunque mi sembra di capire che non necessita pull-up o resistenze varie ma per me il problema principale sta nel codice dove non riesco a capire come modificare per aggiungere i vari canali (Pin input) e le varie uscite (Pin output) se duplico questo semplice codice per i vari canali mi da sempre errore, oppure ogni pin accende qualsiasi led e non quello specifico spinto mi potresti cortesemente fare un esempio di come possa moltiplicare ingressi e uscite ?
la scheda touch che sto utilizzando ha la capacitò di essere gestita anche con solo due fili ma li sarebbe morte certa per me ad esempio ho trovato un codice che faceva al caso per me ma li stesso il programmatore chiedeva che avrei dovuto inserire le varie uscite ma non ho capito come fare, per curiosità ti allego il codice

 /*
 *  Arduino code for 16 button (4x4) TTP229 touch module
 *  
 *  original source: http://itimewaste.blogspot.com/2014/12/arduino-code-for-ttp229-touch-16-button.html
 *  
 * updated by Ahmad Shamshiri for Robojax.com 
 * on December 08, 2018 at 20:48 in Ajax, Ontario, Canada

watch video instruction for this code:https://youtu.be/2AEzQtKhBBY
Get this code and other Arduono codes from Robojax.com
 * 
  * This code is "AS IS" without warranty or liability. Free to be used as long as you keep this note intact.* 
 * This code has been download from Robojax.com
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
 
#include <SPI.h>

#define SCLpin 3 // define SCL pin
#define SDOpin 2 // define SDO pin

// the pins you want to turn ON or OFF or connect to relay
const int outputPins[] ={4, 5, 6, 7, 8, 9, 10, 11, 12, 13,A0,A1,A2,A3,A4,A5};// define output pins 

#if 0
  #define DEBUG_BUTTON16(a) (a)
#else
  #define DEBUG_BUTTON16(a)
#endif

#if 1
  #define DEBUG_STATUS(a) (a)
#else
  #define DEBUG_STATUS(a)
#endif


#pragma pack(push, 0)

// TBD: Replace with proper interrupt pin macros. It does not seem to be defined for atmega328p or I am incapable of finding it
#ifndef INT0_PIN
#ifdef __AVR_ATmega328P__
#define INT0_PIN 2
#else
  #warning Define INT0_PIN for this microcontroller to use interrupt
#endif
#endif

#ifndef INT1_PIN 
#ifdef __AVR_ATmega328P__
#define INT1_PIN 3
#else
  #warning Define INT1_PIN for this microcontroller to use interrupt
#endif
#endif

uint32_t g_intCount = 0;

struct CTtp229ButtonEvent
{
  uint8_t ButtonNumber : 5;         // ButtonNumber != 0 : Event is present. if equals 0, no event is received
  uint8_t IsButtonReleased : 1;     // True = Button is pressed. False = Button is released
};

class CTtP229TouchButton
{
  struct CTtp229Prop
  {
    uint16_t  SclPin : 6;
    uint16_t  SdoPin : 6;
    uint16_t  Is16Button : 1;
#if defined(INT0_PIN) || defined(INT1_PIN)
    uint16_t  HasPendingInterrupt : 1;
    uint16_t  IgnoreNextEvent : 1;            // When reading 16th key and if it is pressed, SDO stays low for 2ms.
                                              // If we enable interrupt before that, then it will trigger after 2ms, only to find the same condition.
                                              // To make things worse, at the end of reading the pin will stay low and generate another interrupt.
                                              // TBD: One possible fix is to send more pulses to make it roll over to HIGH. Have to find out if all 16 keys can be pressed in multi-key scenario (NOT supported yet).    
    uint16_t UnhandledButtonPresses;
#endif
    uint16_t PreviousButtonValue;
  };
  
  static CTtp229Prop g_prop;

  //
  //    Internal function that captures the data from TTP229 on which key is pressed.
  //  Currently, this function only supports one key being pressed. Multi-key press needs to be added later.
  // 
  //  Return Value : Bit field of buttons pressed
  //
  static uint16_t GetPressedButton()
  {
    DEBUG_BUTTON16(Serial.println("GetPressedButton : Enter "));
    uint16_t buttonsPressed = 0;
    // Need to generate the LOW and then HIGH on the clock and read the value from data when clock is back high.
    // As per the specification, the TTP229 chip can support 512Khz. This translates to approximately 2us for a cycle. So introducing clock with fall and raise each of 1us.
    uint8_t maxCnt = g_prop.Is16Button ? 16 : 8;
    for(uint8_t ndx = 0; ndx < maxCnt; ndx++ )
    {
      digitalWrite(g_prop.SclPin, LOW);
      delayMicroseconds(1);
      digitalWrite(g_prop.SclPin, HIGH);
      
      int val = digitalRead(g_prop.SdoPin);

      delayMicroseconds(1);  // Technically this can be moved after the if for most atmel microcontrollers. But if there is a really fast one (now/future) and the next call to GetPressedButton made immediately, we might overclock TTP229. Being safe here

      if( LOW == val )
      {
        buttonsPressed |= (1 << ndx);
      }      
    }
    
    DEBUG_BUTTON16(Serial.print("GetPressedButton : Exit. Return Value : ")); 
    DEBUG_BUTTON16(Serial.println(buttonsPressed));

    return buttonsPressed;
  }
  
#if defined(INT0_PIN) || defined(INT1_PIN)
  // Detaching the interrupt after receiving the data can cause problem in sleeping. If the interrupt is not properly dispatched, it can lead to permanent sleep and can't wake up from button
  static void HandleButtonEvent()
  {
    if( g_prop.IgnoreNextEvent )
    {
      // We ignored an event. Now we will accept the event
      g_prop.IgnoreNextEvent = false;
    }
    else
    {
      g_prop.HasPendingInterrupt = true;
      g_intCount++;
    }
  }
  
  static void SetInterruptHandler()
  {
#ifdef INT0_PIN    
    if( INT0_PIN == g_prop.SdoPin ) 
    {
      DEBUG_BUTTON16(Serial.println("Configure : With interrupt 0"));
      EIFR = 0x01; // Clear INTF0 flag
      attachInterrupt(0, HandleButtonEvent, RISING); // The pin goes down for 93us and then raises that is when the device is ready (technically after 10us)      
    }
#endif 

#ifdef INT1_PIN    
    if( INT1_PIN == g_prop.SdoPin ) 
    {
      DEBUG_BUTTON16(Serial.println("Configure : With interrupt 1"));
      EIFR = 0x02; // Clear INTF1 flag
      attachInterrupt(1, HandleButtonEvent, RISING); // The pin goes down for 93us and then raises that is when the device is ready (technically after 10us)      
    }
#endif 
  }
  
  static void RemoveInterruptHandler()
  {
#ifdef INT0_PIN
    if( INT0_PIN == g_prop.SdoPin ) 
    {
      detachInterrupt(0);
    }
#endif

#ifdef INT1_PIN 
    if( INT1_PIN == g_prop.SdoPin ) 
    {
      detachInterrupt(1);
    }
#endif
  }
#endif

  //
  //    Returns button number being pressed. High bit indicates more changes present
  //
  static uint8_t GetButtonNumberFromFlag(uint16_t buttonsChanged)
  {
    uint16_t flag = 1;
    for(uint8_t ndx = 1; ndx <=16; ndx++, flag <<= 1)
    {
      if( (buttonsChanged & flag) != 0 )
      {
        if( (buttonsChanged & ~flag) != 0 )
        {
          // Some other bit is present
          ndx |= 0x80;
        }
        
        return ndx;
      }
    }
    
    return 0;
  }
  
  public:
  //
  //    Setup the TTP229 Touch button on this input.
  //
  // Inputs:
  //     sclPin  - Clock Pin of the button (3rd from left on button, connected to arduino's digital pin number)
  //     sdoPin  - Data pin to read from the button (4th pin from left on button, connected to arduino's digital pin number)
  //     is16Button - true = 16 buttons board. false = 8 button board
  //
  static void Configure(int sclPin, int sdoPin, bool is16Button = true)
  {
    DEBUG_BUTTON16(Serial.println("Configure : Enter")); 
    
    g_prop.SclPin = sclPin;
    g_prop.SdoPin = sdoPin;
    g_prop.Is16Button = is16Button;

    g_prop.PreviousButtonValue = 0;

    // Configure clock as output and hold it high
    pinMode( sclPin, OUTPUT ); 
    digitalWrite(sclPin, HIGH);    
    
    // Configure data pin as input
    pinMode( sdoPin, INPUT);
    
    DEBUG_BUTTON16(Serial.print("Button Configuration

SCL Pin : "));
    DEBUG_BUTTON16(Serial.println(sclPin));
    DEBUG_BUTTON16(Serial.print("SDO Pin : "));
    DEBUG_BUTTON16(Serial.println(sdoPin));
    DEBUG_BUTTON16(Serial.print("Number of Keys : "));
    DEBUG_BUTTON16(Serial.println(is16Button ? 16 : 8));

#if defined(INT0_PIN) || defined(INT1_PIN)
    g_prop.UnhandledButtonPresses = 0;
    g_prop.HasPendingInterrupt = false;
    g_prop.IgnoreNextEvent = false;
    SetInterruptHandler();
#endif

    DEBUG_BUTTON16(Serial.println("Configure : Exit"));
  }
  
  //
  //    Get the current status from the 16 button touch device
  //
  //   Return Value : Returns the bitflag of the keys pressed. returns 0, if no key is pressed.
  //
  static uint16_t GetButtonStatus()
  {
#if defined(INT0_PIN) || defined(INT1_PIN)
    g_prop.HasPendingInterrupt = 0;
#endif

    uint16_t returnValue = GetPressedButton();
    
#if defined(INT0_PIN) || defined(INT1_PIN)
    returnValue |= g_prop.UnhandledButtonPresses;    // and also include any data that was received that we have not sent yet.
    g_prop.UnhandledButtonPresses = 0;
#endif

    g_prop.PreviousButtonValue = returnValue;

    return returnValue; 
  }
  
  //
  //    Gets the event from the button. This is useful for monitoring press and release only. 
  // Each button press will generate max 2 events, one for press and another for release. When the button is press and held, this method will return no event.
  // If the calls were not made often enough, the events could be missed. For instance, you might get 2 pressed, followed by 4 pressed, which automatically means 2 released in single key mode.
  //
  // Return Value : if ButtonNumber is 0, then no event
  //
  static CTtp229ButtonEvent GetButtonEvent()
  {
    CTtp229ButtonEvent returnValue = {0, 0};
    uint8_t buttonNumber;

    DEBUG_BUTTON16(Serial.print("Old Value  : "));
    DEBUG_BUTTON16(Serial.println(g_prop.PreviousButtonValue));


#if defined(INT0_PIN) || defined(INT1_PIN)
    if(
#if defined(INT0_PIN)
    INT0_PIN == g_prop.SdoPin 
#endif
#if defined(INT0_PIN) && defined(INT1_PIN)
    ||
#endif
#if defined(INT1_PIN)
    INT1_PIN == g_prop.SdoPin 
#endif
    ) 
    {
      // Interrupts are used. Check if we have interrupt
      if( g_prop.HasPendingInterrupt )
      {
        RemoveInterruptHandler();                 // From this point upto SetInterruptHandler is called, ensure there is no return path that will leave without SetInterruptHandler
      }
      else
      {
        DEBUG_BUTTON16(Serial.println("GetButtonEvent: No interrupt pending"));
        return returnValue;
      }
    }
#endif

    uint16_t currValue = GetPressedButton();

#if defined(INT0_PIN) || defined(INT1_PIN)
    currValue |= g_prop.UnhandledButtonPresses; // Get any previously returned but not returned now values also into the mix
#endif

    uint16_t changes = g_prop.PreviousButtonValue ^ currValue;
    uint16_t pressed = (changes & currValue);
    uint16_t released = (changes & g_prop.PreviousButtonValue);

    // First check if any key is that is pressed and generate press event
    if( 0 != pressed )
    {
      buttonNumber = GetButtonNumberFromFlag(pressed);
      returnValue.ButtonNumber = (buttonNumber & 0x7F);
      
      uint16_t mask = (1 << (returnValue.ButtonNumber -1));
      // set the new notified button into prev
      g_prop.PreviousButtonValue |= mask;
      
#if defined(INT0_PIN) || defined(INT1_PIN)
      g_prop.UnhandledButtonPresses = currValue;
      g_prop.UnhandledButtonPresses = currValue & ~g_prop.PreviousButtonValue;    // clear unhandled for this bit, just in case
#endif
    }
    else if(0 != released)
    {
      buttonNumber = GetButtonNumberFromFlag(released);
      returnValue.ButtonNumber = (buttonNumber & 0x7F);

      // The unmatching bit whose previous value of 1 means, it is released
      returnValue.IsButtonReleased = true;
      
      // clear the notified release button
      g_prop.PreviousButtonValue &= ~(1 << (returnValue.ButtonNumber -1));
    }

    
#if defined(INT0_PIN) || defined(INT1_PIN)
    
    if(((!returnValue.IsButtonReleased || (0 == pressed))   // We handle release but no pending press
          && ((buttonNumber & 0x80) == 0 )) // or more button changes are detected
        || (returnValue.ButtonNumber == 0) )    // safety in case interrupt and data mismatch or code bug
    {
      // No more button notification pending
      g_prop.HasPendingInterrupt = false;
    }
    else
    {
      DEBUG_BUTTON16(Serial.println("not Clearing interrupt"));
    }

    g_prop.IgnoreNextEvent = digitalRead(g_prop.SdoPin) == LOW; // If the pin is still low at the end of reading, ignore next event which is for data finished raise
    DEBUG_BUTTON16(Serial.print(g_prop.IgnoreNextEvent ? "Ignoring next event

" : "Not ignoring

"));
    
    // All the data has been read. Now reactivate the interrupt
    SetInterruptHandler();
#endif
    
    DEBUG_BUTTON16(Serial.print("currValue : "));
    DEBUG_BUTTON16(Serial.println(currValue));
    DEBUG_BUTTON16(Serial.print("Changes    : "));
    DEBUG_BUTTON16(Serial.println(changes));
    DEBUG_BUTTON16(Serial.print("Button N   : "));
    DEBUG_BUTTON16(Serial.println(buttonNumber));
    DEBUG_BUTTON16(Serial.print("Unhandled  : "));
    DEBUG_BUTTON16(Serial.println(g_prop.UnhandledButtonPresses));
    DEBUG_BUTTON16(Serial.print("ButtonRelease : "));
    DEBUG_BUTTON16(Serial.println(returnValue.IsButtonReleased));
    DEBUG_BUTTON16(Serial.print("buttonNumber : "));
    DEBUG_BUTTON16(Serial.println(buttonNumber));
    DEBUG_BUTTON16(Serial.print("Pending interrupts :"));
    DEBUG_BUTTON16(Serial.println(g_prop.HasPendingInterrupt));
    
    return returnValue;
  }
  
#if defined(INT0_PIN) || defined(INT1_PIN)
  static bool HasEvent()
  {
#if defined(INT0_PIN)
    if( INT0_PIN == g_prop.SdoPin )
    {
      return g_prop.HasPendingInterrupt;
    }
#endif

#if defined(INT1_PIN)
    if( INT1_PIN == g_prop.SdoPin )
    {
      return g_prop.HasPendingInterrupt;
    }
#endif
    
    return true;
  }
#endif

};

CTtP229TouchButton::CTtp229Prop CTtP229TouchButton::g_prop;
CTtP229TouchButton g_ttp229Button;

#define TTP16Button g_ttp229Button
#pragma pack(pop)

void setup()
{
  // Robojax TTP229 4x4 (16 button) touch pad
  Serial.begin(9600);

   for (int i=0; i<16; i++)
   {
    pinMode(outputPins[i], OUTPUT);// set pins as output
   }
  
  DEBUG_STATUS(Serial.println("===================================================================="));
  DEBUG_STATUS(Serial.println("Robojax 16 button Touch Test"));  
  DEBUG_STATUS(Serial.println("===================================================================="));
  
  TTP16Button.Configure(SCLpin, SDOpin);
}

void TestStatus()
{
  uint8_t buttonNumber = TTP16Button.GetButtonStatus();
  
  if( 0 != buttonNumber )
  {
    DEBUG_STATUS(Serial.print("Button Pressed : "));
    DEBUG_STATUS(Serial.println(buttonNumber));
  }

  delayMicroseconds(2500); // TTP229 document says it will reset the output if 2ms idle + little bit safety
}

void TestEvent()
{
#if defined(INT0_PIN) || defined(INT1_PIN)
  if( TTP16Button.HasEvent())
#endif
  {
    CTtp229ButtonEvent buttonEvent = TTP16Button.GetButtonEvent();
    
    if( 0 != buttonEvent.ButtonNumber )
    {
      if( buttonEvent.IsButtonReleased )
      {
        DEBUG_STATUS(Serial.print("Button Released: "));
        digitalWrite(outputPins[buttonEvent.ButtonNumber -1], HIGH);
      }
      else
      {
        DEBUG_STATUS(Serial.print("Button Pressed : "));
        digitalWrite(outputPins[buttonEvent.ButtonNumber -1], LOW);
      }
      DEBUG_STATUS(Serial.print(buttonEvent.ButtonNumber));
      DEBUG_STATUS(Serial.print(" pin: "));
      DEBUG_STATUS(Serial.println(outputPins[buttonEvent.ButtonNumber -1]));
    }
    else
    {
#if defined(INT0_PIN) || defined(INT1_PIN)
        DEBUG_STATUS(Serial.println("Are you not using interrupt? Should never come here for interrupt based system."));
#endif
    }
    
    //Serial.print("CurrentTime : "); Serial.println(millis());
    delayMicroseconds(2500); // TTP229 document says it will reset the output if 2ms idle + little bit safety. Not required if using interrupts
  }
  
}

void loop()
{
  //TestStatus();
  TestEvent();
}
 

https://robojax.com/learn/arduino/?vid=robojax_16ch_touch_TTP229

1pcs-16-Way-XD-62B-TTP229-Capacitive-Touch-Switch-Digital-Sensor-Module-B

Infatti, con quella scheda non ne avete bisogno, e non avrete nemmeno bisogno di un sistema anti-rimbalzo, quella tastiera lo ha integrato e non avrete alcun problema. Ma non dimenticate il consiglio di @gpb01 qui sopra se utilizzate un normale pulsante.

E ora passiamo al codice e partendo dal primo che hai postato:
In linea di principio funziona correttamente per un pulsante, ma ....

  • Perché quel delay? .Non fa nulla ed è inutile.
  • Non è necessario utilizzare una variabile per memorizzare lo stato di un pin di uscita, perché anche se è definito come OUTPUT possiamo sempre eseguire una digitalRead e conoscere il suo stato.

Detto questo, il tuo codice iniziale potrebbe assomigliare a questo:

  #define LED_1 13                // LED collegato al pin digitale 13
  #define BUTTON_1 7              // pin di input dove è collegato il pulsante
  int val = 0;                    // si userà val per conservare lo stato del pin di input
  int vecchio_val_1 = 0;          // si userà vecchio_val per conservare lo stato del pin di input al passo precedente

  void setup() {
  pinMode(LED_1, OUTPUT);       // imposta il pin digitale come output
  pinMode(BUTTON_1, INPUT);     // imposta il pin digitale come input
  }


  void loop() {
  val = digitalRead(BUTTON_1);  // legge il valore dell'input e lo conserva
  // controlla se è accaduto qualcosa
  if ((val == HIGH) && (vecchio_val_1 == LOW)){
    digitalWrite (LED_1,!digitalRead (LED_1));//cambiare il led nello stato opposto
   }
  vecchio_val_1 = val;            // ricordiamo il valore precedente di val
  }

Per aggiungere più led, (o nel tuo caso relè), è sufficiente ripetere quanto fatto per uno: definire il nuovo relè, il relativo pulsante e creare una variabile per memorizzare lo stato precedente del nuovo set. Ad esempio per due relè:

#define rele_1 13                // LED 1 collegato al pin digitale 13
#define rele_2 12                // LED 2 collegato al pin digitale 12
#define BUTTON_1 7              // pin di input dove è collegato il pulsante di led 1
#define BUTTON_2 8              // pin di input dove è collegato il pulsante di led 2

int val = 0;                    // si userà val per conservare lo stato del pin di input
int vecchio_val_1 = 0;          // si userà vecchio_val per conservare lo stato del pin di input 1 al passo precedente
int vecchio_val_2 = 0;          // si userà vecchio_val per conservare lo stato del pin di input 2 al passo precedente

void setup() {
  pinMode(rele_1, OUTPUT);       // imposta il pin digitale come output
  pinMode(rele_2, OUTPUT);       // imposta il pin digitale come output
  pinMode(BUTTON_1, INPUT);     // imposta il pin digitale come input
  pinMode(BUTTON_2, INPUT);     // imposta il pin digitale come input
}

void loop() {
  val = digitalRead(BUTTON_1);  // legge il valore dell'input e lo conserva
  // controlla se è accaduto qualcosa
  if ((val == HIGH) && (vecchio_val_1 == LOW)) {
    digitalWrite (rele_1, !digitalRead (rele_1)); //cambiare il led nello stato opposto
  }
  vecchio_val_1 = val;            // ricordiamo il valore precedente di val

  val = digitalRead(BUTTON_2);  // legge il valore dell'input e lo conserva
  // controlla se è accaduto qualcosa
  if ((val == HIGH) && (vecchio_val_2 == LOW)) {
    digitalWrite (rele_2, !digitalRead (rele_2)); //cambiare il led nello stato opposto
  }
  vecchio_val_2 = val;            // ricordiamo il valore precedente di val
}

Per l'ottavo pulsante che spegne tutto, fai esattamente lo stesso, ma invece di dare l'ordine

  digitalWrite (rele_?, !digitalRead (rele_?));

Dovrai dare i 7 ordini di spegnimento:

  digitalWrite (rele_?, LOW);

Saluti.

1 Like

Mi scuso se non ti ho scritto prima, lavorando in ospedale questi giorni non ho avuto del tempo.
Grazie per l'esempio ed il tempo che mi hai dedicato e grazie anche ai consigli di gpb01, il vostro aiuto a noi principianti e davvero prezioso, perchè non avendo delle basi e capire da quanto si legge in giro non è sempre facile, è bello imparare ogni giorno cose nuove ,
Grazie
il delay che riferisci pensavo che andasse bene per dargli del tempo e non creare interferenze
proverò ad eseguire quanto detto :slight_smile:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.