pinMode IN/OUT

Buonasera a tutti,
ho una piccola domanda, ho messo su un piccolo progetto con dei sensori capacitivi che attivano e disattivano dei relè. Gli stessi relè possono essere attivati anche via software, attraverso la seriale, con un client in java che comunica quale relè attivare e disattivare. A questo punto, tutte le volte che interagisco con un relè via software, vorrei poter cambiare anche lo stato del sensore capacitivo.
Per intenderci:

  1. Tocco il sensore (toggle): lo stato del sensore capacitivo è in HIGH, lo stato del relè è in HIGH
  2. Disattivo il medesimo relè via software: lo stato del sensore capacitivo è in HIGH, lo stato del relè è in LOW

Io vorrei poter impostare anche il sensore capacitivo in LOW.

Purtroppo, considerando che in setup() stabilisco che il sensore capacitivo è di INPUT, questo non mi permette di cambiare stato al sensore via software.
Esiste una sorta di dichiarazione IN/OUT per i pin digitali? oppure cosa mi consigliate? non so dove sbattere la testa

grazie sempre

Scusa che senso ha "cambiare lo stato del sensore capacitivo" ??? :astonished: :astonished: :astonished:

Non stai mica parlando di un interruttore bistabile ... :roll_eyes:

Il sensore capacitivo ti dice solo che qualcuno ha toccato il sensore e che tu devi commutare il relè, ma lo stato del relè tu lo conserverai in una variabile ... quindi aggiorna quella e basta no ?

Guglielmo

gpb01:
Scusa che senso ha "cambiare lo stato del sensore capacitivo" ??? :astonished: :astonished: :astonished:

Non stai mica parlando di un interruttore bistabile ... :roll_eyes:

Il sensore capacitivo ti dice solo che qualcuno ha toccato il sensore e che tu devi commutare il relè, ma lo stato del relè tu lo conserverai in una variabile ... quindi aggiorna quella e basta no ?

Guglielmo

Proprio perché è bistabile il problema si presenta (http://www.robot-italy.com/it/standalone-toggle-capacitive-touch-sensor-breakout-at42qt1012.html)

Ma quello è un interruttore bistabile ... indipendentemente che sia capacitivo o meccanico ...
... per come avevi posto la domanda uno pensava che tu avessi un capacitivo collegato ad Arduino !!!

Con quello credo che hai poco da fare non mi sembra abbia "ingressi di comando da SW" ... è come chiedere come da software spostare un interruttore meccanico ... :roll_eyes:

Guglielmo

P.S. : Se dovevi fare una cosa come quella che descrivi, perdona, ma ... hai sbagliato progetto e scelto i sensori errati !
I relè li dovevi gestire sempre e solo da SW e da SW dovevi leggere dei veri sensori capacitivi ...

Rispondo da profano, visto che quello che hai è, come dice Guglielmo, un switch bistabile alla fine, e visto che ormai c'è l'hai, perchè non trattarlo come se fosse un normale pulsante e lavorare con una variabile che cambia stato, 1 tocco, accende, 1 tocco spegne, da seriale la stessa cosa. Unico neo, credo, il led del pulsante che resta acceso magari mentre lo fai spegnere da seriale e questo non è molto bello (più per altro, perché potrebbe trarre in inganno dello stato del switch rispetto a quello del Relè).
E se usassi un normale pulsante ? (se il led è necessario, lo attivi mediante lo stesso pin del relè con le dovute protezioni per le correnti di ritorno (diodo e resistenza se non ricordo male )...

Saebbe piú semplice usare un pulsatnte capacitivo e un un sensore capacitivo con funzionalitá di interuttore bistabile.
Definisci una variabile che quando é HIGH inverte la lettura del interuttore capacitivo. Questa variabile la setti im modo da avere il settaggio voluto del relé quandi lo comandi via Software.

Interuttore a LOW. Setti via PC il relé attivi la negazione del input Interuttore.

boolean interuttore = 0;  // stato interuttore capacitivo 
boolean inverti =0;   
boolean Rele =0;   // stato relé ; uscita
boolean software =0; // stato del comando Software.
boolean softwareold =0; // variabile per reagire solo ai cambi di stato del Interuttore e del comando Software.
boolean interuttoreold = 0;  // variabile per reagire solo ai cambi di stato del Interuttore e del comando Software.
boolean modificamanuale=0; // variabile per segnare 

loop() {
interuttore = digitalread(pinInteruttore);
leggi comando da software;

if(software != softwareold)     // solo in caso di cambiament stato ; accende o spegne il rele
{
if (software ==HIGH && Rele ==HIGH) inverti =0;  // non invertire
if (software ==LOW && Rele ==LOW) inverti =0;  // non invertire
if (software ==HIGH && Rele ==LOW) inverti =1;  //  invertire
if (software ==LOW && Rele ==HIGH) inverti =1;  //  invertire
}

if(interuttore != interuttoreold || software != softwareold)
{
if (interuttore ==HIGH && inverti ==0)
   {
   digitalWrite( pinRele, HIGH );
   Rele =HIGH;
   }
if (interuttore ==LOW && inverti ==0) 
   {
   digitalWrite( pinRele, LOW );
   Rele =LOW;
   }
if (interuttore ==HIGH && inverti ==1) 
   {
   digitalWrite( pinRele, LOW );
   Rele =LOW;
   }

if (interuttore ==LOW && inverti ==1)    
   {
   digitalWrite( pinRele, HIGH );
   Rele =HIGH;
   }
softwareold = software;
interuttoreold = interuttore;
}
}

Si puó facilmente condensare il codice ma ho voluto scriverlo cosí esteso per far capire il funzionamento.

Ciao Uwe

Hiper, Uwe ... sento da qui lo stridio delle vostre unghie sul vetro mentre cercate di arrampicarvi sugli specchi ... :grin: XD :grin: XD :grin:

Che a questo mondo qualsiasi porcheria si possa fare, va bene, ma di base c'è ... che NON è quello il sensore capacitivo che andava usato ... la stessa robot-italy ne vende uno identico ma monostrabile ... lo tocchi, commuta, lo lasci ricommuta, il che sarebbe l'ideale per dire al SW che vuoi cambiare stato ... :wink:

Poi, ripeto ... tutto si può usare ... MALE ... :stuck_out_tongue: :stuck_out_tongue: :stuck_out_tongue:

Guglielmo

Non vi scaldate per favore!! :sweat_smile: io da profano in materia mi arrangio con quello che ho, se poi non è quello che mi serve e serve BENE, allora accantono tutto e riparto da capo e prendo quello che mi serve, purtroppo senza una scuola dietro (essendo autodidatta in tutto, elettronica e programmazione) mi baso molto sul Try & Error. Come si dice, di necessità virtù. Ovviamente ,poi, mi escono delle C£$&!!te pazzesche! come diceva un noto comico :grin:

io avrei usato un volgare e silvestre pulsante dal valore di 20 Centesimi (se lo tocchi con un guanto alle dita funziona, con un capacitivo lo dubito e poi, il costo fa il resto...)

Grazie ragazzi per i vostri consigli...

@hiperformance71
Volendo potrei anche usare il toggle come un pulsante monostabile e per quanto riguarda il LED si può anche disattivare tagliando un jumper, perciò il problema non si pone. Però non mi piace dover usare qualcosa che lavora in un certo modo e adattarlo per un altro scopo.
gpb01 ha ragione

@gpb01
Per quanto riguarda il monostabile, ho comprato anche quello su robot-italy e li ho entrambi, sia i bistabili che monostabili. Preferivo i bistabili perché mi risparmiavano un po di codice, sopratutto se i pulsanti da gestire sono 8.
Ma considerando che sn ancora all'inizio del progetto, posso ancora cambiare le carte in tavola.
Nella documentazione ufficiale ho trovato un codice che potrebbe fare al caso mio http://arduino.cc/en/Tutorial/Debounce. Il problema, ripeto, è che dovrei gestire 8 pulsanti.
Ho replicato il codice del link convertendo tutte le variabili in array e mettendo tutto su un ciclo for ma ho dei problemi:
Toccando un sensore monostabile si accende sia il relè associato che anche un'altro relè al quale non è collegato alcun sensore.
Come potete vedere dal codice, dal 22 al 29 sono i pin dedicati ai relè, dal 32 al 39 sono i pin dedicati ai sensori.
Ad esempio... se tocco il sensore 32 si accende il relè 22 e anche il 23 se al 23 non è collegato un sensore.
Non riesco a capire dove sbaglio.

Grazie sempre per il vostro prezioso aiuto

const int nPin = 8;

int LEDstate[100];
int buttonState[100];
int lastButtonState[100];

long lastDebounceTime[100];
long debounceDelay[100];
  
void setup()
{
  Serial.begin(9600);
  for(int x=22; x<22+nPin; x++){
    pinMode(x, OUTPUT);
    digitalWrite(x, HIGH);
    pinMode(x+10, INPUT);
  }
  
  for(int j=32; j<32+nPin; j++){
    LEDstate[j]         = HIGH;
    lastButtonState[j]  = LOW;
    lastDebounceTime[j] = 0;
    debounceDelay[j]    = 50;
  }
  
}
  
void loop()
{
  
  for(int x=22; x<22+nPin; x++){

    int inX = 10+x;
    
    // read the state of the switch into a local variable:
    int reading = digitalRead(inX);
  
    // check to see if you just pressed the button 
    // (i.e. the input went from LOW to HIGH),  and you've waited 
    // long enough since the last press to ignore any noise:  
  
    // If the switch changed, due to noise or pressing:
    if (reading != lastButtonState[inX]) {
      // reset the debouncing timer
      lastDebounceTime[inX] = millis();
    } 
    
    if ((millis() - lastDebounceTime[inX]) > debounceDelay[inX]) {
      // whatever the reading is at, it's been there for longer
      // than the debounce delay, so take it as the actual current state:
  
      // if the button state has changed:
      if (reading != buttonState[inX]) {
        buttonState[inX] = reading;
  
        // only toggle the LED if the new button state is HIGH
        if (buttonState[inX] == HIGH) {
          LEDstate[inX] = !LEDstate[inX];
        }
      }
    }
    // set the LED:
    digitalWrite(x, LEDstate[inX]);
  
    // save the reading.  Next time through the loop,
    // it'll be the lastButtonState:
    lastButtonState[inX] = reading;
    
  }
  
}

avete mai provato librerie come questa GitHub - c9jester/ToggleButton: An Arduino library for using a pushbutton as an on/off switch.? che dite, vale la pena utilizzare soluzioni simili?

ho creato anche una libreria basata sull'esempio http://arduino.cc/en/Tutorial/Debounce, in questo modo mi viene più semplice tenere pulito il codice creando un istanza della classe per pin che voglio utilizzare.

ne posto il codice che può essere utile anche a qualcun altro:

ClickButton.h

#ifndef ClickButton_H
#define ClickButton_H

#if (ARDUINO <  100)
#include <WProgram.h>
#else
#include <Arduino.h>
#endif


#define CLICKBTN_PULLUP HIGH


class ClickButton
{
  public:
    ClickButton();
    void setPin(uint8_t buttonPin, uint8_t ledPin);
    void Update();
    int buttonPin;    // the number of the pushbutton pin
    int ledPin;      // the number of the LED pin

    int ledState;         // the current state of the output pin
    int buttonState;             // the current reading from the input pin
    int lastButtonState;   // the previous reading from the input pin

    // the following variables are long's because the time, measured in miliseconds,
    // will quickly become a bigger number than can be stored in an int.
    long lastDebounceTime;  // the last time the output pin was toggled
    long debounceDelay;    // the debounce time; increase if the output flickers
};

#endif

ClickButton.cpp

#include "ClickButton.h"

ClickButton::ClickButton()
{
  ledState = HIGH;         // the current state of the output pin
  buttonState;             // the current reading from the input pin
  lastButtonState = LOW;   // the previous reading from the input pin

  // the following variables are long's because the time, measured in miliseconds,
  // will quickly become a bigger number than can be stored in an int.
  lastDebounceTime = 0;  // the last time the output pin was toggled
  debounceDelay = 50;    // the debounce time; increase if the output flickers
  buttonPin;
  ledPin;
}

void ClickButton::setPin(uint8_t buttonPini, uint8_t ledPini)
{
  buttonPin = buttonPini;
  ledPin = ledPini;
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);

  // set initial LED state
  digitalWrite(ledPin, ledState);
}

void ClickButton::Update()
{

// read the state of the switch into a local variable:
  int reading = digitalRead(buttonPin);
  Serial.println(reading);
  // check to see if you just pressed the button 
  // (i.e. the input went from LOW to HIGH),  and you've waited 
  // long enough since the last press to ignore any noise:  

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  } 
  
  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:

    // if the button state has changed:
    if (reading != buttonState) {
      buttonState = reading;

      // only toggle the LED if the new button state is HIGH
      if (buttonState == HIGH) {
        ledState = !ledState;
      }
    }
  }
  
  // set the LED:
  digitalWrite(ledPin, ledState);

  // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastButtonState = reading;

}

Come richiamare le istanze

#include "ClickButton.h"
ClickButton button1;
ClickButton button2;

void setup()
{
  
  button1.setPin(32, 22); //primo pin è quello del pulsante (INPUT), il secondo è quello del relè (OUPUT)
  button2.setPin(38, 28);

}

void loop()
{
  // Update button state  
  button1.Update();
  button2.Update();
}

Il problema che si presenta, comunque, è sempre lo stesso dell'esempio precendente:

Toccando un sensore monostabile si accende sia il relè associato che anche un'altro relè al quale non è collegato alcun sensore. non riesco a capire per quale motivo.
Qualcuno che abbia idea di quale possa essere il problema?

Nessuno che possa aiutarmi?

Ho eseguito un paio di test e sembrerebbe che ci sia una sorta di ritorno di corrente verso i sensori monostabili quando i relè sono collegati ad arduino. Per fare un semplice test, ho inizializzato 4 relè e 4 sensori monostabili

void setup(){
 //Relè
  pinMode(22, OUTPUT);
  digitalWrite(22, LOW);
  pinMode(23, OUTPUT);
  digitalWrite(23, LOW);
  pinMode(24, OUTPUT);
  digitalWrite(24, LOW);
  pinMode(25, OUTPUT);
  digitalWrite(25, LOW);

  //Sensori
  pinMode(32, INPUT);
  digitalWrite(32, LOW);
  pinMode(33, INPUT);
  digitalWrite(33, LOW);
  pinMode(34, INPUT);
  digitalWrite(34, LOW);
  pinMode(35, INPUT);
  digitalWrite(35, LOW);

}

Inizializzando Arduino soltanto con il codice che ho postato, i relè si eccitano (relè a logica negata) e, molto spesso, si accendono anche i LED dei sensori monostabili (Generalmente il LED del monostabile si accende soltanto se viene toccato). I sensori sono collegati a dei PIN che ho dichiarato di INPUT e ciò non dovrebbe accadere... inoltre, nelle volte in cui non si accendono da soli, se tocco i sensori è come se si incantassero, cioè toccandoli restano accesi e ci rimangono oppure altri si spengono dopo qualche secondo.
Se rilancio il tutto senza relè collegati i sensori funzionano regolarmente e non si incantano mai. Quello che penso è che ci sia una specie di ritorno di corrente sui sensori da parte dei relè o qualcosa di simile.
Ho provato anche a mettere, sul pin di ogni sensori, una resistenza da 10kohm per evitare che ci sia corrente in entrata sul sensore ma il problema si presenta comunque.

Secondo voi cosa potrebbe essere.

ma i relè come li attivi? direttamente da arduino no! meglio farlo attraverso un Mosfet o anche un darlington tipo UNL2003, se usi un Mosfet, devi anche collegare un diodo per eliminare le correnti di flyback del relè quando viene diseccitato.

grazie mille per il tuo aiuto :), purtroppo non sono molto ferrato in elettronica e mi sto arrangiando documentandomi in rete... Per un niubbo, quando nascono intoppi di questo tipo, non si sa cosa cercare nello specifico e ci si ferma spiazzati... Anche un piccolo consiglio, come quello che mi hai dato, può essere di grande aiuto per avere qualcosa da cui ripartire e potersi documentare :). Ritornando al problema.... Si in effetti al momento li attivo tramite arduino ma avevo in mente di alimentarli esternamente ad arduino... Scusa l'ignoranza della domanda, come dovrei collegare i MOSFET? Ti sarei grato se riuscissi a darmi una mano con delle piccole indicazioni o qualche link da seguire, mi sono bloccato su questo problema e non ho la più pallida idea di come procedere
Io ho un alimentatore da 5v 3A che avevo pensato di utilizzare per alimentare sensori e relè (e successivamente anche altro), in modo da renderli indipendenti da arcuino.

grazie ancora per il tuo aiuto

non capisco questo passaggio

//Sensori
pinMode(32, INPUT);
digitalWrite(32, LOW);

e' un input, perche' lo vorresti mettere LOW ?

  1. Si, il tuo problema puo' essere disturbi sull'alimentazione
    Che scheda rele' usi ?

  2. Mi controlli una cosa...

se c'e' continuita' , sulla breadboard, dal primo foro all'ultimo di una riga di alimentazione ( quella rossa o blu )

Personalmente non collegherei mai un relè direttamente ad un pin Arduino, essi hanno una piccola capacità di assorbire/dare Corrente di pochi mA ed anche ammettendo che trovassimo un relè con piccolissima corrente di eccitazione, comunque, per il fatto di essere un carico induttivo (come un solenoide, un motore elettrico o una bobina magnetica di un altoparlante per esempio) genera una corrente/tensione di ritorno detta flyback al momento di sospendere la nostra eccitazione al device, queste correnti/tensioni solitamente sono brevissime ma hanno la caratteristica di essere molto superiori a quelle di pilotaggio, avvolte nell'ordine di anche 40-70 volts ma durano pochi ms al massimo. Per evitare danni ai componenti che attivano carichi induttivi, si usa un diodo.
In rete troverai un casino di materiale al riguardo di come collegare un relè, il problema è il tipo di relè, vi sono di piccola tensione (5V) media (12V) e alta tensione (oltre 24V secondo me) nonché quelli a corrente AC per pilotare utenze a 220V per esempio.
A prescindere dal relè utilizzato, io lo piloterei con un integrato idoneo, si possono usare transistor, FET, MOSFET, IGBT o Darlington. Di questi solo i darlington hanno incorporato il diodo di protezione. Ecco alcune pagine interessanti che dovresti leggere:

http://forum.arduino.cc/index.php?topic=159154.0
http://forum.arduino.cc/index.php?topic=52512.0
http://fritzing.org/projects/controling-8-relay-with-arduino-mega-adk

http://forum.arduino.cc/index.php?PHPSESSID=1e4a4883d1494c29861a458c565d7b79&topic=36133.msg265830#msg265830
http://blog.elettronicain.it/2013/01/04/le-mie-avventure-con-arduino/

Non ti preoccupare per il fatto di essere un "niubbo" in elettronica, anch'io lo sono, solo che con qualche anno di pratica in più, ma alcune cose le ho imparate facendo pratica, vedi?

Per l'osservazione fatta da Brunello: Come mai metti un pin in input e poi lo metto low? che io sappia avvolte si mette il pin in Ingresso High per così poter utilizzare il pull-up interno per poter "sentire" segnali LOW, l'ho visto fare specialmente con pin interrupt.

Immagino che il test suggerito sia per verificare che le masse che alimentano i relè ed arduino siano condivise, se non lo sono, possono portare a problematice di disturbi vari come questi da te indicati.

hiperformance71:
Per l'osservazione fatta da Brunello: Come mai metti un pin in input e poi lo metto low? che io sappia avvolte si mette il pin in Ingresso High per così poter utilizzare il pull-up interno per poter "sentire" segnali LOW, l'ho visto fare specialmente con pin interrupt.

Non solo per gli interrupt. Serve a dare uno stato definito al pin, perché un pin lasciato "libero" è flottante, ossia capta qualunque cosa, anche una mano avvicinata al pin. Attivando la R di pull-up interna, si da uno stato alto ben definito.
Non vorrei che pensasse che mettendo il pin in input e poi facendo il digitaWrite con LOW si attivasse una R di pull-down interna, che sulle MCU Atmel non esiste.

Buongiorno a tutti,
allora inizio con il ringraziarvi per il vostro prezioso aiuto, adesso inizio a capirci qualcosina sulla problematica anche se ancora c'è molta strada per vedere della luce in fondo al tunnel :).

  1. La scheda relè che utilizzo lavora a 5V: http://www.amazon.it/Modulo-Relè-Relay-Canali-Arduino/dp/B00E370JAC/ref=sr_1_4?ie=UTF8&qid=1397376512&sr=8-4&keywords=relè

  2. Per quanto riguarda l'istruzione digitalWrite(PIN, LOW) per il pin in INPUT avete ragione. Era lì inizialmente in HIGH per il pull-up, l'ho messo in LOW perché pensavo potesse andare anche in pull-down (come accennava leo72) ma a quanto pare non si può fare. Inoltre solo adesso, cercando su internet, mi sono accorto che il pull-up si può mettere anche con pinMode(PIN, INPUT_PULLUP);

  3. Ho controllato le piste di alimentazione sulla breardboard con un multimetro e confermo la continuità di entrambi i poli su tutta la pista. Per curiosità mia ho anche controllato la continuità delle piste interne, naturalmente in verticale, ed anche quelle sono ok.

  4. Vi posto anche un video del problema. Come si vede, toccando in sequenza i sensori capacitivi monostabili, si accendono i relè ma gli ultimi due sensori (ma in realtà, toccando continuamente i sensori, capita con tutti in maniera casuale) restano attivi, molto probabilmente per uno dei disturbi di ritorno tensione di cui parlavate.

@hiperformance71
Grazie per i link, adesso gli do subito un'occhiata, anche perché non sono molto informato su MOSFET o Darlington e devo prima documentarmi in merito :). Grazie mille anche per l'incoraggiamento :), quando lavoro su un piccolo progetto di elettronica e sorgono problemi di questo tipo, il web è l'unica fonte a disposizione che può aiutare a capire ma spesso mi ritrovo a non saper cosa cercare... anche una piccola indicazione può essere di grande aiuto, e per questo ringrazio ancora tutti voi :wink:

Con la scheda che stai usando, tutto il discorso dei mosfet/darlington ecc decade! mi sembra di intravedere degli integrati e dei diodi per ogni relè, quindi in questa applicazione non devi aggiungerne perché già dotata o almeno così mi sembra dalla foto.

Per il discorso del pin pull-up ha ragione Leo, anche se non l'ho mai usato per tale scopo, perchè ho sempre preferito mettervi io la resistenza di pull_up quindi non ci mai fatto caso delle altre possibilità, solo ultimamente l'ho vista usare con gli interrupt appunto dove ovviamente, un pin "flottante", "erratico" (stato logico incerto quindi) potrebbe scattare senza ragione apparente.

Comunque, fai qualche prova su quel pin, se ti serve il pull down, metticelo esterno, magari una resistenza da 4,7-10K e ri testa il tutto. Se nemmeno cos' dovesse funzionare a dovere, ti suggerirei di controllare le schede comprate separatamente, per accertare che siano apposto.