Problema codice

Buonasera a tutti
Ho un problema, quando stacco il cavo USB e poi lo riattacco il programma che ho caricato sulla mia scheda arduino non mi rimane caricato. Per essere più precisi vorrei utilizzare Arduino senza collegarlo al PC bensì utilizzarlo tramite un alimentatore. Il programma si basa su di un interrupt. Grazie

Io_me:
Sempre quando si attacca il cavo USB Arduino si resetta, per vedere se stai trasmettendo un programma

... leggi bene cosa ha scritto prima di rispondere!

Guglielmo

P.S.: Inoltre il reset avviene solo al momento dell'apertura della seriale ... e all'arrivo dell'alimentazione (se prima Arduno era spento).

not:
Ho un problema, quando stacco il cavo USB e poi lo riattacco il programma che ho caricato sulla mia scheda arduino non mi rimane caricato.

Che il programma non resti caricato è impossibile. Il codice viene scritto nella Flash la quale, anche senza alimentazione, conserva il codice.

Probabilmente c'è qualche errore che fa si che il programma, senza il collegamento con il PC, si comporti diversamente e, non potendolo tu vedere via monitor seriale, hai l'impressione che si sia cancellato, ma ... il programma è sempre li, altrimenti ... la MCU è da buttare :smiley: :smiley: :smiley:

Guglielmo

ok grazie! posso postare il mio codice? magari mi potete aiutare a capire dove sbaglio. il tutto si basa su di un pulsante che interrompe il lampeggio di un Led al quale è legato un interrupt. grazie :slight_smile:

not:
ok grazie! posso postare il mio codice? magari mi potete aiutare a capire dove sbaglio.

Si, certo (… mi raccomando, in conformità al regolamento, punto 7, racchiuso tra i tag CODE che, in fase di edit, ti inserisce il bottone </> … primo a sinistra).

Guglielmo

#include <HX711.h>
#define LED1 2
#include <SD.h>
#include <SPI.h> 
#define PULSANTE 9

File myFile;
int pinCS = 10;
HX711 cell(5,4);

int val = 0;
volatile byte stato = LOW;
long lastBlink = millis();
int ledState = LOW;
float zero;
float lecture;
float attuale;
int potentiometerPin = A0;
int value = 0;
int potentiometer = 0;
int spostamento = 0;
int delta_spostamento = 0;
int spostamentoprec = 0;

void debug(){
 
  value = analogRead(potentiometerPin); // leggo valore potenziometro
  attuale = cell.read();
  lecture = attuale - zero;

  if ( value - potentiometer >= 0 ){
    
    spostamento = spostamento  + (value - potentiometer);
    delta_spostamento = spostamento - spostamentoprec;
    
    if ( lecture < 0 ){
      
      lecture = lecture*(-1);
      
      }
      
      } else {
        
        spostamento = spostamento + (potentiometer - value);
        delta_spostamento = spostamento - spostamentoprec;
        
        if ( lecture < 0 ){
          
          lecture = lecture*(-1);
          
          }
      }
    
  potentiometer = value;
  spostamentoprec = spostamento;
  zero = attuale;
  
  Serial.print(delta_spostamento);
  Serial.print(",");
  Serial.println(lecture);
  
  myFile = SD.open("test.txt",FILE_WRITE);
  
  if (myFile) {
    
    myFile.print(millis());
    myFile.print(",");
    myFile.print(delta_spostamento);
    myFile.print(",");
    myFile.println(lecture);
    myFile.close(); // close the file
    
    }else {
      
      Serial.println("error opening test.txt");
      
      }
    
}

void setup(){
  
  Serial.begin(9600);
  pinMode(pinCS,OUTPUT);
  
  if (!SD.begin()) { // Initialize SD card
    
    Serial.println("Could not initialize SD card."); // if return value is false, something went wrong.
    
    }
    
    if (SD.exists("test.txt")) { // if "file.txt" exists, fill will be deleted
      
      Serial.println("test exists.");
      
      if (SD.remove("test.txt") == true) {
        
        Serial.println("Successfully removed file.");
        
        } else {
          
          Serial.println("Could not removed file.");
          
          }
     }
     
  attachInterrupt( digitalPinToInterrupt(2), debug, HIGH );
  pinMode( LED1, OUTPUT );
  Serial.println( "Setup Done" );
  zero = cell.read();
  potentiometer = analogRead(potentiometerPin);
  pinMode(PULSANTE, INPUT);

}

void loop(){
 val = digitalRead(PULSANTE);
  
   
 digitalWrite( LED1, ledState );
 if ((val != HIGH)) {
 if ( millis() - lastBlink == 40){
   
   lastBlink = millis();
   if ( ledState == LOW )
     ledState = HIGH;
   else
     ledState = LOW;

 }
 }else if(val == HIGH){
  ledState =LOW;
 }
}

Il programma deve prendere ogni 25 Hz (40 millisecondi) il valore di un potenziometro e quello di una cella di carico. Il campionamento è stato grazie ad un interrupt governato da un Led. Quando un pulsante viene premuto l’acquisizione si ferma. Ora il mio problema è che una volta staccata l’alimentazione e poi ricollegata il programma non prende più l’acquisizione bensì rimane spento. Per intenderci il led rimane spento invece che lampeggiare. Grazie dell’aiuto e scusate se posso essere stato poco chiaro

#include <HX711.h>
#define LED1 2
#include <SD.h>
#include <SPI.h>
#define PULSANTE 9

File myFile;
const int pinCS = 10;
HX711 cell(5, 4);

int val = 0;
volatile byte stato = LOW;
long lastBlink = millis();
int ledState = LOW;
float zero;
float lecture;
float attuale;
int potentiometerPin = A0;
int value = 0;
int potentiometer = 0;
int spostamento = 0;
int delta_spostamento = 0;
int spostamentoprec = 0;

void debug() {

  value = analogRead(potentiometerPin); // leggo valore potenziometro
  attuale = cell.read();
  lecture = attuale - zero;

  if ( value - potentiometer >= 0 ) {

    spostamento = spostamento  + (value - potentiometer);
    delta_spostamento = spostamento - spostamentoprec;
    if ( lecture < 0 ) lecture = lecture * (-1);

  } else {

    spostamento = spostamento + (potentiometer - value);
    delta_spostamento = spostamento - spostamentoprec;
    if ( lecture < 0 ) lecture = lecture * (-1);

  }

  potentiometer = value;
  spostamentoprec = spostamento;
  zero = attuale;

  Serial.print(delta_spostamento);
  Serial.print(",");
  Serial.println(lecture);

  myFile = SD.open("test.txt", FILE_WRITE);

  if (myFile) {

    myFile.print(millis());
    myFile.print(",");
    myFile.print(delta_spostamento);
    myFile.print(",");
    myFile.println(lecture);
    myFile.close(); // close the file

  } else {

    Serial.println("error opening test.txt");
    blinkErorr(6);

  }

}

void setup() {
  Serial.begin(9600);
  pinMode(pinCS, OUTPUT);
  pinMode(LED1, OUTPUT );
  pinMode(LED_BUILTIN, OUTPUT);

  if (!SD.begin()) { // Initialize SD card
    Serial.println("Could not initialize SD card."); // if return value is false, something went wrong.  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
    blinkErorr(4);
  }

  if (SD.exists("test.txt")) { // if "file.txt" exists, fill will be deleted
    Serial.println("test exists.");
    if (SD.remove("test.txt") == true) {
      Serial.println("Successfully removed file.");
    } else {
      Serial.println("Could not removed file.");
      blinkErorr(5);
    }
  }

  attachInterrupt( digitalPinToInterrupt(2), debug, HIGH );
  Serial.println( "Setup Done" );
  zero = cell.read();
  potentiometer = analogRead(potentiometerPin);
  pinMode(PULSANTE, INPUT);
}


void loop() {
  val = digitalRead(PULSANTE);
  digitalWrite( LED1, ledState );
  if ((val != HIGH)) {
    if ( millis() - lastBlink == 40) {
      lastBlink = millis();
      if ( ledState == LOW )
        ledState = HIGH;
      else
        ledState = LOW;
    }
  } else if (val == HIGH) {
    ledState = LOW;
  }
}

void blinkErorr(int num) {
  for (x = 0; x < num; x++) {
    delay(500);
    digitalWrite(LED_BUILTIN, LOW);
    delay(500);
    digitalWrite(LED_BUILTIN, HIGH);
  }
}

Ho inserito una funzione per far lampeggiare il led integrato sul pin 13 quando si incontra un errore.
Non avendo le librerie del sensore non ho potuto verificare se il programma compila.
Quando non hai il PC collegato è inutile mettere il debug sulla seriale, meglio far lampeggiare un led o ancora meglio un display a 7 segmenti per visualizzare stati o errori.

Giusto una prima risposta "al volo", guardando il tuo codice la prima cosa che ti consiglio è cambiare la riga:

if ( millis() - lastBlink == 40) {

in:

if ( millis() - lastBlink >= 40) {

altrimenti se il loop() non becca esattamente i 40ms dopo l'ultimo blink, non blinka più.

Grazie delle risposte! @docdoc il mio problema è che voglio i dati esattamente ogni 40 ms, putroppo è questa la maggiore difficoltà. Ho cambiato il codice e lavoro tramite un pulsante, cioè fintantochè viene premuto acquisisce mentre se il suo valore scende a zero no. ora sono riuscito ad abbassare fino “>= 20” ma mi serve qualcosa tipo “==”

#define PULSANTE 9 
#include <HX711.h>
#include <SD.h>
#include <SPI.h>

HX711 cell(5,4);
File myFile;
int pinCS = 10;

boolean STATO = LOW;
int potentiometerPin = A0;
int value = 0;
int potentiometer = 0;
int spostamento = 0;
int delta_spostamento = 0;
int spostamentoprec = 0;
unsigned long referenceMillis = 0;
unsigned long currentMillis = 0;
unsigned long previousMillis = 0;
unsigned long targetMillis = 0;
long zero;
long lecture;
long attuale;

void setup(){
  Serial.begin(9600);
  pinMode(pinCS,OUTPUT);
  pinMode (PULSANTE, INPUT_PULLUP);  
    if (!SD.begin()) { // Initialize SD card
    Serial.println("Could not initialize SD card."); // if return value is false, something went wrong.  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  
  }

  if (SD.exists("test.txt")) { // if "file.txt" exists, fill will be deleted
    Serial.println("test exists.");
    if (SD.remove("test.txt") == true) {
      Serial.println("Successfully removed file.");
    } else {
      Serial.println("Could not removed file.");
     
    }
  }
  zero = cell.read();
  potentiometer = analogRead(potentiometerPin);
}

void loop(){
  STATO = digitalRead(PULSANTE);
  if(STATO == 1) {
    currentMillis = millis();
    if ( currentMillis - previousMillis >= 20 ) {
    value = analogRead(potentiometerPin);
    attuale = cell.read();
    lecture = attuale - zero;
    if ( value - potentiometer >= 0 ){
      spostamento = spostamento  + (value - potentiometer);
      delta_spostamento = spostamento - spostamentoprec;
      if ( lecture < 0 ){
        lecture = lecture*(-1);
        }
      }
     else {
        spostamento = spostamento + (potentiometer - value);
        delta_spostamento = spostamento - spostamentoprec;
        if ( lecture < 0 ){
        lecture = lecture*(-1);
        }
    }
    potentiometer = value;
    spostamentoprec = spostamento;
    zero = attuale;
    
    Serial.println(millis());
    myFile = SD.open("test.txt",FILE_WRITE);

      if (myFile) {
              
         myFile.print(millis());
         myFile.print(",");
         myFile.print(delta_spostamento);
         myFile.print(",");
         myFile.println(lecture);
         myFile.close(); // close the file
            
       }else {
              
              Serial.println("error opening test.txt");
        } 
    
  }
  }
}

come faccio ad avere intervalli “regolari”?

not:
come faccio ad avere intervalli “regolari”?

Con millis/micros più regolare di così non si può:

if(micros() - t >= periodo)
{
    t += periodo;
    ....
}

ok grazie! un modo alternativo ci sarebbe? Ho provato ad usare la funzione timer.h o un interrupt ma nessun miglioramento

not:
Grazie delle risposte! @docdoc il mio problema è che voglio i dati esattamente ogni 40 ms, putroppo è questa la maggiore difficoltà.
come faccio ad avere intervalli "regolari"?

Con quella precisione, secondo me non puoi.
Il fatto è che il loop() è un processo continuo ma non è detto che parta né ogni millisecondo (o meno) né esattamente quando millis() è pari al precedente evento più esattamente 40. Se anche solo UNA volta la differenza dovesse per qualche ragione (es. un interrupt) non essere esattamente 40, ma 41, con quel codice non avrai MAI PIU' alcun evento perché l'if() sarà sempre falsa.
Considera anche che il timer interno che è usato da millis() non è del tutto preciso, quindi 40 millisecondi potrebbero a volte essere in realtà qualche decimale in più o in meno, e ad un certo punto basta che "salti" l'intero che stai daccapo col problema che non fa più niente.
In ogni caso mettere ">= 40" non significa quindi che potrebbe partire a 50ms o più, ma sarà quasi sempre 40, forse qualche volta 41. Ma non avendo la certezza di avere 40, devi mettere il ">=".

Se su un Arduino a 16MHz usi un timer a 16 bit (sul ATmega328P il Timer 1) e programmi il prescaler a 64 e carichi TCNTx (x = 1 per Timer 1) al valore 55536 (0xD8F0), hai un periodo di esattamente 40msec. indipendentemente da quello che fa il codice ... lo puoi usare per generare un interrupt che esegui esattamente con quel periodo.

Guglielmo

Grazie mille Guglielmo, è la spiegazione che stavo cercando

gpb01:
Se su un Arduino a 16MHz usi un timer a 16 bit (sul ATmega328P il Timer 1) e programmi il prescaler a 64 e carichi TCNTx (x = 1 per Timer 1) al valore 55536 (0xD8F0), hai un periodo di esattamente 40msec. indipendentemente da quello che fa il codice ... lo puoi usare per generare un interrupt che esegui esattamente con quel periodo.

Bella questa cosa, non la conoscevo! Cercherò, ma intanto hai magari un link dove trovare ulteriori info e qualche test?

gpb01:
Se su un Arduino a 16MHz usi un timer a 16 bit (sul ATmega328P il Timer 1) e programmi il prescaler a 64 e carichi TCNTx (x = 1 per Timer 1) al valore 55536 (0xD8F0), hai un periodo di esattamente 40msec. indipendentemente da quello che fa il codice ... lo puoi usare per generare un interrupt che esegui esattamente con quel periodo.

Guglielmo

Aggiungerei solo qualche info:

  1. un link a pagina sui timer e registri del 328: link
  2. un bel libro che spiega anche questa parte: Arduino la guida essenziale scritto da uno degli admin, in parecchi l'abbiamo comprato, fatto molto bene, ci sono le basi ma anche parti avanzate
  3. naturalmente se cambi le impostazioni su Timer1, eventuali librerie che si appoggiano al Timer1 (esempio Servo) potrebbero avere problemi.

Nid, hai dimenticato il link in assoluto più importante ... il DATASHEET del ATmega328P !!! E' da li che fondamentalmente si ricavano tutte le informazioni :smiley: :smiley: :smiley:

Guglielmo