Visualizzazione post con etichetta MKR1400. Mostra tutti i post
Visualizzazione post con etichetta MKR1400. Mostra tutti i post

venerdì 15 marzo 2019

Progetto Due

Il progetto due prevede un sistema ad alimentazione solare con una Arduino MKR1400  collegata ad un accelerometro ADXL345 che invia un SMS nel momento in cui il sensore registra un movimento



Per l'alimentazione solare ho usato un modulo basato su CN3065 per la ricarica della LiPo con una LiPo da 2000 mAh ed un pannello solare da 0.5W. I cavi sono stati saldati sulla piastra invece su usare i connettori JST (per la batteria ed il pannello solare ci sono sia i connettori JST che le basi per saldare...per l'output su SYS ho collegato i cavi dietro al JST)


Le connessioni sono piuttosto semplici

ADXL345 : il pin di interrupt e' collegato a  D8 di MKR. Gli altri cavi sono 3.3V, GND SDA ed SCL in modo standard



Un problema che e' stato riscontrato e' che l'interrupt 1 dell'ADXL345 passa da uno stato High ad uno Low mentre la MKR si aspetta l'esatto contrario per attivare l'interrupt
Per questo motivo il collegamento tra INT1 di ADXL345 e D8 di MKR1400 passa attraverso un circuito di logic inverter (in pratica una porta NOT) realizzato con un transistor 2n2222a
Sull'IN e' stato collegato INT1 di ADXL345 e su out D8 di MKR




Circuito di prova...l'interrutore serve a simulare il cambio di stato del pin
Per la versione finale sara' usato l'integrato SN74HC04N, un integrato con 6 porte NOT a tensioni tra 2 e 6V



Il consumo in standby e' di circa 20 mA (mi aspettavo di meno...forse ho sbagliato qualcosa??)




mentre quando viene attivato il GSM e si invia l'SMS la corrente raggiunge un picco di circa 220 mA con valori stabili per una decina di secondi sopra i 100 mA

Questo e' lo sketch di funzionamento
----------------------------------------------------
#include "ArduinoLowPower.h"
#include <SparkFun_ADXL345.h> 
#include <MKRGSM.h>


// Pin per wakeup
const int interruptPin = 8;
// GSM
GSM gsmAccess;
GSM_SMS sms;

ADXL345 adxl = ADXL345();           
volatile int invia = 0;


void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(interruptPin, INPUT);
  delay(5000);
  adxl.powerOn();                     
  adxl.setRangeSetting(2);
  adxl.setInterruptLevelBit(1);
  adxl.setSpiBit(0);                  
  adxl.setActivityXYZ(1, 1, 1);       
  adxl.setActivityThreshold(50);      
  adxl.setTapDetectionOnXYZ(1, 1, 1);
  adxl.setTapThreshold(50);         
  adxl.setTapDuration(55);    
  adxl.ActivityINT(1);
  adxl.singleTapINT(1);
      
  LowPower.attachInterruptWakeup(interruptPin, funzione, CHANGE);
}

void loop() {  

if (invia == 1){
       bool connected = false;
       digitalWrite(LED_BUILTIN, HIGH);
       delay(500);
       digitalWrite(LED_BUILTIN, LOW);
       delay(500);
       while (!connected) {
        if (gsmAccess.begin() == GSM_READY) {
          connected = true;
          } 
       delay(1000);
       sms.beginSMS("+393471xxxxxx");
       sms.print("Luca mi ha toccato");
       sms.endSMS(); 
       invia = 0;  
       }
  }    

LowPower.sleep();
}

void funzione() {
   invia = 1;
}

mercoledì 6 marzo 2019

Differenza FreeRTOs su Arduino AVR e SAMD21 e ESP-Wroom-32

La principale differenza nell'implementazione di FreeRTOs in ESP32 ed in Arduino Uno (ovvero AVR ATMega328) e' il fatto che Esp32 e' un processore dual core. FreeRTOs riesce a distribuire il carico del lavoro tra i core. Nell'esempio sottostante (ripreso da qui), fatto girare su Esp-Wroom-32, si vede che il main loop ed il task vengono eseguiti su due core differente in modo parallelo


Viene creato un task generico che fa un solo loop e poi si autodistrugge (vTaskDelete(NULL)) mentre il loop principale continua a rimanere in esecuzione.
-------------------------------------------------------------------------
void setup() {

  Serial.begin(9600);
  delay(1000);

  Serial.print("Setup: Executing on core ");
  Serial.println(xPortGetCoreID());

  xTaskCreate(
                    genericTask,       /* Task function. */
                    "genericTask",     /* String with name of task. */
                    10000,             /* Stack size in words. */
                    NULL,              /* Parameter passed as input of the task */
                    2,                 /* Priority of the task. */
                    NULL);             /* Task handle. */
 delay(2000); 

}

void loop() {
  Serial.print("Main Loop: Executing on core ");
  Serial.println(xPortGetCoreID());
  delay(1000);
}

void genericTask( void * parameter ){
    Serial.print("Created task: Executing on core ");
    Serial.println(xPortGetCoreID());
    vTaskDelete(NULL);
}

-----------------------------------------------------------------------------------------
Setup: Executing on core 1
Created task: Executing on core 0
Main Loop: Executing on core 1
Main Loop: Executing on core 1

Main Loop: Executing on core 1


 Se si usa #include <Arduino_FreeRTOS.h> si vedra' che non esiste nemmeno la funzione xprtoGetCoreID perche' ATMega328 e' un processore single core...i task vengono eseguiti su un unico core dividendo i tick del processore tra i vari task come un time sharing

Le cose non cambiano con la serie Arduino MKR che montano SAM D21 Cortex M0-+ (solo alcuni  Cortex di fascia alta sono multi core) 

martedì 5 febbraio 2019

Arduino MKR1400

E' arrivata sulla scrivania la concorrente diretta della Particle Electron (e molto probabilmente la vincitrice), la Arduino MKR1400 una MKR1000 con in aggiunta un modulo GSM

La scheda funziona con le microSIM e non con le nanoSIM (come la Electron) e supporta senza nessun problema Things Mobile



Una prima cosa strana: la scheda mi e' arrivata senza antenna nonostante sullo store ne viene segnalata la presenza. Ho utilizzato quella della Electron

Ho avuto problemi di connessione con la porta seriale. In caso di necessita' di reset della scheda si deve premere due volte in modo ravvicinato il tasto di reset

Il connettore della LiPo e' di tipo JST-PH
Per controllare il livello della batteria si puo' usare questo sketch
----------------------------------------------------------------------------
void setup() {
  Serial.begin(9600);
}

void loop() {
  int sensorValue = analogRead(ADC_BATTERY);
  float voltage = sensorValue * (4.3 / 1023.0);
  Serial.print(voltage);
  Serial.println("V");
}
----------------------------------------------------------------------------

Per inviare SMS il codice piu' semplice e' il seguente.
Negli sketch deve essere sempre inserita la parte in giallo di configurazione della seriale
Alla SIM e' stato rimosso il pincode per cui non e' necessario configuralo nello sketch

----------------------------------------------------------------------------
#include <MKRGSM.h>


GSM gsmAccess;
GSM_SMS sms;

void setup() {
 Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  
bool connected = false;

  while (!connected) {
    if (gsmAccess.begin() == GSM_READY) {
      connected = true;
    } else {
      Serial.println("Not connected");
      delay(1000);
    }
  }

  Serial.println("GSM initialized");
}

void loop() {
  delay(1000);
  sms.beginSMS("+393471xxxxxxx");
  sms.print("Prova MKR14000");
  sms.endSMS(); 
  Serial.println("Inviato");
  delay(60000);
}
--------------------------------------------------------

Nel momento di provare ad usare la MKR1400 in accoppiata con un ADXL345 sono entrato in una serie di problemi apparentemente senza uscita perche' ogni volta che cercavo di configurare il canale I2C la scheda perdeva la configurazione della porta seriale su USB e non eseguiva nessuno sketch

Dopo un'oretta di prove a caso ho messo un delay di 5 secondi all'inizio della funzione di setup()  e l'accelerometro ha iniziato a funzionare in modo corretto

MKR1400 e ADXL345



----------------------------------------------------------
/
#include <MKRGSM.h>

GSM gsmAccess;
GSM_SMS sms;

#include <SparkFun_ADXL345.h>         // SparkFun ADXL345 Library

ADXL345 adxl = ADXL345();             // USE FOR I2C COMMUNICATION
int interruptPin = 2;                 // Setup pin 2 to be the interrupt pin (for most Arduino Boards)

void setup(){
  
  Serial.begin(9600);  
  while (!Serial)
  {}; 
  delay(5000);
  Serial.println("SMS Messages Sender");

  
  // Start the serial terminal
  Serial.println("SparkFun ADXL345 Accelerometer Hook Up Guide Example");
  Serial.println();
  
  adxl.powerOn();                     // Power on the ADXL345

  adxl.setRangeSetting(16);           // Give the range settings
                                      // Accepted values are 2g, 4g, 8g or 16g
                                      // Higher Values = Wider Measurement Range
                                      // Lower Values = Greater Sensitivity

  adxl.setSpiBit(0);                  // Configure the device to be in 4 wire SPI mode when set to '0' or 3 wire SPI mode when set to 1
                                      // Default: Set to 1
                                      // SPI pins on the ATMega328: 11, 12 and 13 as reference in SPI Library 
   
  adxl.setActivityXYZ(1, 0, 0);       // Set to activate movement detection in the axes "adxl.setActivityXYZ(X, Y, Z);" (1 == ON, 0 == OFF)
  adxl.setActivityThreshold(75);      // 62.5mg per increment   // Set activity   // Inactivity thresholds (0-255)

  adxl.setInactivityXYZ(1, 0, 0);     // Set to detect inactivity in all the axes "adxl.setInactivityXYZ(X, Y, Z);" (1 == ON, 0 == OFF)
  adxl.setInactivityThreshold(75);    // 62.5mg per increment   // Set inactivity // Inactivity thresholds (0-255)
  adxl.setTimeInactivity(10);         // How many seconds of no activity is inactive?

  adxl.setTapDetectionOnXYZ(0, 0, 1); // Detect taps in the directions turned ON "adxl.setTapDetectionOnX(X, Y, Z);" (1 == ON, 0 == OFF)

  // Set values for what is considered a TAP and what is a DOUBLE TAP (0-255)
  adxl.setTapThreshold(50);           // 62.5 mg per increment
  adxl.setTapDuration(15);            // 625 μs per increment
  adxl.setDoubleTapLatency(80);       // 1.25 ms per increment
  adxl.setDoubleTapWindow(200);       // 1.25 ms per increment

  // Set values for what is considered FREE FALL (0-255)
  adxl.setFreeFallThreshold(7);       // (5 - 9) recommended - 62.5mg per increment
  adxl.setFreeFallDuration(30);       // (20 - 70) recommended - 5ms per increment

  // Setting all interupts to take place on INT1 pin
  //adxl.setImportantInterruptMapping(1, 1, 1, 1, 1);     // Sets "adxl.setEveryInterruptMapping(single tap, double tap, free fall, activity, inactivity);" 
                                                        // Accepts only 1 or 2 values for pins INT1 and INT2. This chooses the pin on the ADXL345 to use for Interrupts.
                                                        // This library may have a problem using INT2 pin. Default to INT1 pin.
  
  // Turn on Interrupts for each mode (1 == ON, 0 == OFF)
  adxl.InactivityINT(1);
  adxl.ActivityINT(1);
  adxl.FreeFallINT(1);
  adxl.doubleTapINT(1);
  adxl.singleTapINT(1);
  
attachInterrupt(digitalPinToInterrupt(interruptPin), ADXL_ISR, RISING);   // Attach Interrupt

}

/****************** MAIN CODE ******************/
/*     Accelerometer Readings and Interrupt    */
void loop(){
  
  // Accelerometer Readings
  int x,y,z;   
  adxl.readAccel(&x, &y, &z);         // Read the accelerometer values and store them in variables declared above x,y,z

  // Output Results to Serial
  /* UNCOMMENT TO VIEW X Y Z ACCELEROMETER VALUES 
  Serial.print(x);
  Serial.print(", ");
  Serial.print(y);
  Serial.print(", ");
  Serial.println(z); */
  
  ADXL_ISR();
  // You may also choose to avoid using interrupts and simply run the functions within ADXL_ISR(); 
  //  and place it within the loop instead.  
  // This may come in handy when it doesn't matter when the action occurs. 

}

/********************* ISR *********************/
/* Look for Interrupts and Triggered Action    */
void ADXL_ISR() {
  
  // getInterruptSource clears all triggered actions after returning value
  // Do not call again until you need to recheck for triggered actions
  byte interrupts = adxl.getInterruptSource();
  
  // Free Fall Detection
  if(adxl.triggered(interrupts, ADXL345_FREE_FALL)){
    Serial.println("*** FREE FALL ***");

    //add code here to do when free fall is sensed
  } 
  
  // Inactivity
  if(adxl.triggered(interrupts, ADXL345_INACTIVITY)){
    Serial.println("*** INACTIVITY ***");
     //add code here to do when inactivity is sensed
  }
  
  // Activity
  if(adxl.triggered(interrupts, ADXL345_ACTIVITY)){
    Serial.println("*** ACTIVITY ***"); 
     //add code here to do when activity is sensed
  }
  
  // Double Tap Detection
  if(adxl.triggered(interrupts, ADXL345_DOUBLE_TAP)){
    Serial.println("*** DOUBLE TAP ***");
     //add code here to do when a 2X tap is sensed
  }
  
  // Tap Detection
  if(adxl.triggered(interrupts, ADXL345_SINGLE_TAP)){
    Serial.println("*** TAP ***");
            bool connected = false;

  // Start GSM shield
  // If your SIM has PIN, pass it as a parameter of begin() in quotes
  while (!connected) {
    if (gsmAccess.begin() == GSM_READY) {
      connected = true;
    } else {
      Serial.println("Not connected");
      delay(1000);
    }
  }
    Serial.println("Luca mi ha toccato");

   delay(1000);
  sms.beginSMS("+3934710xxxxxx");
  sms.print("Luca mi ha toccato");
  sms.endSMS(); 
  Serial.println("Inviato");
  delay(60000);


  } 
}



Debugger integrato ESP32S3

Aggiornamento In realta' il Jtag USB funziona anche sui moduli cinesi Il problema risiede  nell'ID USB della porta Jtag. Nel modulo...