Prestazione Arduino Nano

La mia domanda è figlia della mia inesperienza, siate clementi!

Stavo pensando a quanto poter "caricare" di lavoro il mio arduino nano v3. Per ora legge gli impulsi da un contatore/misuratore simil Enel e mi calcola il consumo di corrente dell'abitazione. Nella peggiore delle ipotesi sono impulsi che avvengono ogni secondo. Ok, qua ci siamo. Vorrei sfruttare il secondo interrupt per fare una cosa analoga per il sensore vento, 2 impulsi al secondo con vento a 10Km/h (vado a memoria). Anche in questo caso, conta il tempo trascorso tra un impulso e l'altro per poi calcolarne la velocità.

Arrivo alla domanda: come posso stabilire quando sono al limite delle capacità di arduino? Sono 16MHz quindi 16.000.000 di istruzioni al secondo, ma esiste un qualcosa per capire se sto arrivando al limite delle potenzialità? Oppure continuo ad aggiungere codice e calcoli fin quando vedo un rallentamento (e come lo posso vedere?
Ogni ciclo di clock sono 0.0625 microsecondi, quindi ogni istruzione dovrebbe essere eseguita in quel tempo.

Probabilmente la domanda farà ridere parecchie persone ma una mia curiosità.

Grazie!

In linea di massima ogni istruzione viene eseguita in un ciclo di clock ma non è così per tutte le istruzioni, per di più si intendono istruzioni semplici scritte in assembler (una istruzione scritta in wiring, il linguaggio di arduino conta decine di istruzioni in asm ). Ora perdonami ma non ho tempo per darti una risposta più esauriente ma vedrai che altri amici del forum lo faranno con piacere, ciaoo

16mhz sono pochi ma non cosi pochi.....
aggiungi, aggiungi......

Istruzioni sono intesi come istruzioni codice macchina che non ha niente a che fare col codice C scritto nello sketch.

La velocitá di esecuzione di uno sketch dipende tanto come é scritto il Sketch. Non posso dirlo in generale se un contaimpulsi di un contatore di energia Elettrica (dove un impulso non eqivale a una quantitá di corrente ma di energia (IUt)) possa coesistere con una misura di velocitá del vento.

Senza che ci fai vedere lo sketch non posso dire nienete.

Ciao Uwe

Ciao Uwe,
probabilmente non mi sono spiegato benissimo, semplicemente, ciò che volevo sapere, era capire se c'era un modo di verificare se arduino ha ancora "capacità di calcolo" prima di provare lo sketch.
In ogni caso il mio programmino è questo (si deve interfacciare al server domotico e quello sotto è solo un esempio):

//For serial set to 0 and for Ethernet set to 1
#define ISIP 0


#if ISIP == 1
#include <EEPROM.h>
#include <SPI.h>       
#include <Ethernet.h>
#include <EthernetUdp.h> 
#endif


// Pin impulso
const int getpulsepin = 2;

// variabili
float assorbimento = 0.0;
unsigned long startime = 0;
unsigned long durata = 0;
int stato = 0;
int pinval = 0;
int durata2 = 0;

//Address of the board.
const byte BoardAdd = 2;

#if ISIP == 1

byte mac[] = {0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02};




//************Do not change anything in Here*****************
int FromHS[10];                                          // *
boolean IsConnected = false;                             // *
#if ISIP == 1                                            // *
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];               // *
EthernetUDP Udp;                                         // *
const unsigned int ServerPort = 8888;                    // *
#endif                                                   // *
void(* resetFunc) (void) = 0;                            // *
//***********************************************************


void setup() {
  HSSetup();
pinMode(getpulsepin, INPUT); // pin del sensore
digitalWrite (getpulsepin, HIGH);//abilito resistenza pull up
}
void loop() {
#if ISIP == 1
  IsUDP();
#endif

   
pinval = digitalRead(getpulsepin);   // legge il pin del sensore
 
    if ((stato == 1) & (pinval == 0)) { // punto di transizione
    durata = millis() - startime;       // calcola la durata della pulsazione
    startime = millis();            // setta il nuovo tempo di partenza 
    assorbimento = 3600.0/durata*10;  // calcola consumo
    SendToHS(1,assorbimento);
    durata2 = durata;
    SendToHS(2,durata2);
    //stato = pinval;
  }
    stato = pinval;         // imposta lo stato uguale alla lettura del pin
    


/*connection status*/


 if (IsConnected == true) {

  }
}

const char* Version = "API1";

byte Byte1,Byte2,Byte3;
int Byte4,Byte5;


void HSSetup() {

#if ISIP == 1
    if (EEpromVersion!=22) {
    ServerIP=HomeseerIP;
    EEPROM.write(2,ServerIP[0]);
    EEPROM.write(3,ServerIP[1]);
    EEPROM.write(4,ServerIP[2]);
    EEPROM.write(5,ServerIP[3]);
    EEPROM.write(250,22); 
    EEpromVersion=22;
  }
Ethernet.begin(mac,ip);
  Udp.begin(localPort);
  Udp.setTimeout(0);
  delay(1000);
SendConnect();
#else
  Serial.begin(115200);
  Serial.flush();
    Serial.print("Connect ");
  Serial.println(BoardAdd);
#endif

  IsConnected = false;

}

void SendConnect()
{
#if ISIP == 0
  Serial.print("Connect ");
  Serial.println(BoardAdd);
#else
        Udp.print("Connect ");
    Udp.print(BoardAdd);
    Udp.endPacket();
    if (ServerIP!=HomeseerIP) {
            Udp.print("Connect ");
      Udp.print(BoardAdd);
      Udp.endPacket();
    }
 
#endif
}


#if ISIP == 1
void IsUDP(){
  int packetSize = Udp.parsePacket();
  if(packetSize)
  {
    IPAddress remote = Udp.remoteIP();
    Byte1 =Udp.parseInt();
    Udp.read(); 
    Byte2 =Udp.read(); 
    Byte3 =Udp.parseInt();
    Byte4 =Udp.parseInt();
    Byte5 =Udp.parseInt();
    DataEvent();
  }
}

#else
void serialEvent() {
  while (Serial.available() > 0) {
    delay(17);


    Byte1 = Serial.parseInt();
    Serial.read();  
    Byte2 = Serial.read(); 
    Byte3 = Serial.parseInt();
    Byte4 = Serial.parseInt();
    Byte5 = Serial.parseInt();
    DataEvent();
  }
}
#endif



void DataEvent() {



  if (Byte1 == BoardAdd) {
    switch (Byte2) {

    case 'c':
      IsConnected = true;
#if ISIP == 1
      if (Udp.remoteIP() != ServerIP) {
        ServerIP=Udp.remoteIP();
        EEPROM.write(2,ServerIP[0]);
        EEPROM.write(3,ServerIP[1]);
        EEPROM.write(4,ServerIP[2]);
        EEPROM.write(5,ServerIP[3]);
      }     
#endif

      break;

    case 'C':   
#if ISIP == 1
      Udp.beginPacket(Udp.remoteIP(), ServerPort);
      Udp.print("Version ");
      Udp.print(BoardAdd);
      Udp.print(" ");
      Udp.print(Version);
      Udp.println(" HS3");
      Udp.endPacket();

      Udp.beginPacket(Udp.remoteIP(), ServerPort);
      delay(100);
      Udp.print("Connected ");
      Udp.println(BoardAdd);
      Udp.endPacket();
#else
      Serial.print("Version ");
      Serial.print(BoardAdd);
      Serial.print(" ");
      Serial.print(Version);
      Serial.println(" HS3"); 
      delay(100);
      Serial.print("Connected ");
      Serial.println(BoardAdd);
#endif
      delay(100);
      IsConnected = false;
      break;

    case 'K':
      delay(200);
#if ISIP == 1
      Udp.beginPacket(Udp.remoteIP(), ServerPort);
      Udp.print("Alive ");
      Udp.println(BoardAdd);
      Udp.endPacket();
      if (Udp.remoteIP() != ServerIP) {
        ServerIP=Udp.remoteIP();
        EEPROM.write(2,ServerIP[0]);
        EEPROM.write(3,ServerIP[1]);
        EEPROM.write(4,ServerIP[2]);
        EEPROM.write(5,ServerIP[3]);
      }     
#else     
      Serial.print("Alive ");
      Serial.println(BoardAdd);
#endif
      break; 
      
      case 'r':
      delay(200);
      resetFunc();  //call reset
      break; 

    case 'O':
      FromHS[Byte3] = Byte4;
      break; 

    case 'D':
      IsConnected = false;
      break;   
    }
  }
}

void SendToHS(byte Device, long Data){
if (IsConnected == true) {
#if ISIP == 1
  Udp.beginPacket(Udp.remoteIP(), ServerPort);
  Udp.print(BoardAdd);
    Udp.print(Data);
  Udp.endPacket();
#else
  Serial.print(BoardAdd);
  Serial.print(" API ");
  Serial.print(Device);
  Serial.print(" ");
  Serial.println(Data);
#endif
}
}

void SendToHS(byte Device, int Data){
if (IsConnected == true) {
#if ISIP == 1
  Udp.beginPacket(Udp.remoteIP(), ServerPort);
  Udp.print(BoardAdd);
  Udp.print(" API ");
  Udp.print(Device);
  Udp.print(" ");
  Udp.print(Data);
  Udp.endPacket();
#else
  Serial.print(BoardAdd);
  Serial.print(" API ");
  Serial.print(Device);
  Serial.print(" ");
  Serial.println(Data);
#endif
}
}

void SendToHS(byte Device, float Data){
if (IsConnected == true) {
#if ISIP == 1
  Udp.beginPacket(Udp.remoteIP(), ServerPort);
  Udp.print(BoardAdd);
  Udp.print(" API ");
  Udp.print(Device);
  Udp.print(" ");
  Udp.print(Data);
  Udp.endPacket();
#else
  Serial.print(BoardAdd);
   Serial.println(Data);
#endif
}
}

Come dicevo, mi piacerebbe sapere se c'è un modo per capire (senza dover fare girare il programma in test) se arduino ha altra capacità di calcolo.

khriss75:
Come dicevo, mi piacerebbe sapere se c'è un modo per capire (senza dover fare girare il programma in test) se arduino ha altra capacità di calcolo.

Esistono due modi per verificare le prestazioni di un micro e se riesce a far girare il software senza colli di bottiglia, il primo prevede l'uso di un vero ICE, oggetto hardware molto costoso, che ti permette di verificare nel mondo reale cosa succede mentre gira il software.
Il secondo sistema prevede l'uso di uno, o più, pin che vengono fatti commutare con precise temporizzazioni da verificare strumentalmente, se i tempi coincidono con quanto previsto vuol dire che il micro lavora correttamente.

astrobeed:
Esistono due modi per verificare le prestazioni di un micro e se riesce a far girare il software senza colli di bottiglia, il primo prevede l'uso di un vero ICE, oggetto hardware molto costoso, che ti permette di verificare nel mondo reale cosa succede mentre gira il software.
Il secondo sistema prevede l'uso di uno, o più, pin che vengono fatti commutare con precise temporizzazioni da verificare strumentalmente, se i tempi coincidono con quanto previsto vuol dire che il micro lavora correttamente.

Bingoooo! O almeno, mi hai dato una bellissima dritta! Verifico con un paio di pin collegati all'oscilloscopio se la temporizzazione è corretta con quella aspettata!

Grazie mille per l'imboccata!

khriss75:
Bingoooo! O almeno, mi hai dato una bellissima dritta! Verifico con un paio di pin collegati all'oscilloscopio se la temporizzazione è corretta con quella aspettata!

Se hai a disposizione un oscilloscopio va benissimo.

Si si, ce l'ho!
Mi hai dato davvero una bella dritta! Karma meritatissimo!
Poca spesa, tanta resa!
Ho bisogno di questa verifica percché non posso permettermi di "perdere" o "rallentare" alcuni dati. Nel caso del controllo dei KWh non ho grossi problemi se la lettura dovesse essere alterata o rallentata, il problema è invece sul sensore vento (che mi alzerebbe quindi la tenda da sole). Se perdo qualche impulso, se rallento qualcosa ecc, oltre a non aver il dato preciso della misura, rallenterei anche la comunicazione Arduino--Server domotico.
E' vero che i test su nuove configurazioni li faccio per sicurezza in parallelo a ciò che è già funzionante, ma questo mi permetterebbe di escludere a priori problemi di carico arduino.

Ancora grazie mille!

Beh diciamo anche che a seconda delle necessità si possono anche implementare soluzioni con più di un Arduino, tipicamente uno (o più) che fa solo da interfaccia (più rapida possibile) per l'acquisizione e pre-elaborazione dei dati dei sensori, e uno "centrale" che prende le decisioni e fornisce i comandi allo stesso Arduino di interfaccia o uno differente dedicato agli attuatori.
Tutto dipende dai tuoi requisiti e aspettative..:wink:
Ciao!

Ciao Alex, quel che dici è assolutamente corretto, però vorrei appunto limitare il numero di arduino da gestire.
Calcola che minimo sono 3 per gli ingressi, 3 per le uscite. Uno per calcolo consumi (lettura implsi), controllo vento (conteggio impulsi anemometro). A quest'ultimo, vorrei aggiungere led IR per la gestione del roomba (pulizia pavimenti) e tv. Ovviamente, quando arriverò al punto di "caricarlo" eccessivamente, ne metterò un altro. Insomma, sui primi 6 arduino (nano) ci sarà uno sketch semplificato e basato solo sulla gestione pin IN oppure OUT, il settimo conterrà uno sketch sicuramente più omplesso che andrà a gestire ed eseguire calcoli particolari.

khriss75:
Calcola che minimo sono 3 per gli ingressi, 3 per le uscite. Uno per calcolo consumi (lettura implsi), controllo vento (conteggio impulsi anemometro).

Addirittura 7? E come minimo? :o :smiley:
Hm, non credo che il numero di Arduino che stai prevedendo sia per una maggiore potenza di calcolo, ma forse più che altro per il numero di ingressi e uscite. Se così fosse, hai già valutato di usare qualche 74HC165 e 74HC595?

Si, si tratta proprio per una questione di I/O.
Non mi va di utilizzare shift register semplicemente perché oramai l'interfaccia di collegamento tra arduino e serverino domotico, legge o scrive ingressi ed uscite direttamente sulla board di arduino.
Inoltre posso mettere un arduino sparso per casa in modo da non dover tirare troppi cavi che arrivano fino al serverino.
Insomma, questione di comodità e pigrizia.
Comunque, con un Arduino Nano ho a disposizione circa 16 IN o OUT.
16 IN mi vanno solo per i sensori perimetrali finestre e porte... 16 per interruttori luce poi ho pulsanti tapparelle ecc.
OUT: motori tapparelle (2 pin, SU e GIU'), alcune prese, pwm per illuminazione RGB, irrigazione, riavvio router, switch... beh... I/O non bastano mai :slight_smile:

hai anche i 7pin analogici che funzionano anche come digitali, quindi 21I/O, togliendo l'usb 19...
usare 3 Arduino solo per aumentare il numero dei pin lascia un pò a desiderare.
dei comunissimi sipo vanno molto più che bene.

A6 e A7 non sono utilizzabili come OUT.
Ho scritto erroneamente 16 perché ho contato solo le uscite degli uln2803, 8+8 OUT.

vbextreme:
usare 3 Arduino solo per aumentare il numero dei pin lascia un pò a desiderare.
dei comunissimi sipo vanno molto più che bene.

Concordo, anche perché si tratta di cambiare poche righe di codice nei punti dove legge gli IN, il resto rimane identico.

Il problema "logistico" invece è secondo me quello più rilevante, stando a quanto dice, per mettere in casa alcuni Nano che a loro volta dialogano con quello "centrale", ma tranne questo, secondo me può quanto meno unificare qualche Nano facendogli fare lavoro "misto". Non so a che punto sia col progetto però, ovviamente se è a buon punto reingegnerizzare il tutto per adottare una topologia più "compatta" potrebbe essere pesante.

Resta il fatto che IMHO per fare solo da IN e/o OUT per alcuni bit non credo ci siano problemi di prestazioni da parte del processore.

Mannaggia a voi :slight_smile: :slight_smile: :slight_smile: ho appena mandato in stampa un paio di PCB di prova. dai, va bene un I/O per ogni pin :slight_smile: :slight_smile: :slight_smile:

Per la rev2 mi sa che opterò per una più oculata gestione dei pin di ingresso ed uscita.