giovedì 31 gennaio 2019

ESP32 Vroom Sleep + Interrupt

Esempio di Esp32 su scheda Esp-Vroom-32 con modalita' di risveglio da Sleep mode mediante un interrupt fisico (in questo caso un contatto sul pin 33)

Per aggiungere la scheda alla IDE di Arduino si deve aggiungere questo link alle additional boards
https://dl.espressif.com/dl/package_esp32_index.json





Queste sono le impostazioni per programmare la scheda nella IDE





tra gli esempi si trova questo codice che imposta la modalita' deeep sleep e risveglio da pin 33
il consumo di corrente e' inferiore a 0.01A (questo e' il limite inferiore del mio misuratore di corrente USB)

=======================================================

/*
Deep Sleep with External Wake Up
=====================================
This code displays how to use deep sleep with
an external trigger as a wake up source and how
to store data in RTC memory to use it over reboots

This code is under Public Domain License.

Hardware Connections
======================
Push Button to GPIO 33 pulled down with a 10K Ohm
resistor

NOTE:
======
Only RTC IO can be used as a source for external wake
source. They are pins: 0,2,4,12-15,25-27,32-39.

Author:
Pranav Cherukupalli <cherukupallip@gmail.com>
*/

#define BUTTON_PIN_BITMASK 0x200000000 // 2^33 in hex

RTC_DATA_ATTR int bootCount = 0;

/*
Method to print the reason by which ESP32
has been awaken from sleep
*/
void print_wakeup_reason(){
  esp_sleep_wakeup_cause_t wakeup_reason;

  wakeup_reason = esp_sleep_get_wakeup_cause();

  switch(wakeup_reason)
  {
    case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
    case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
    case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
    default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
  }
}

void setup(){
  Serial.begin(115200);
  delay(1000); //Take some time to open up the Serial Monitor

  //Increment boot number and print it every reboot
  ++bootCount;
  Serial.println("Boot number: " + String(bootCount));

  //Print the wakeup reason for ESP32
  print_wakeup_reason();

  esp_sleep_enable_ext0_wakeup(GPIO_NUM_33,1); //1 = High, 0 = Low

  //If you were to use ext1, you would use it like
  //esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK,ESP_EXT1_WAKEUP_ANY_HIGH);

  //Go to sleep now
  Serial.println("Going to sleep now");
  esp_deep_sleep_start();
}

void loop(){
  }

Beta testing Alexa Skills

Per sviluppare Alexa Skills puo' essere necessario un programma di beta testing. Cio' e' possibile con l'unica (e non banale) limitazione che tutti i beta tester siano registrati come developer presso Amazon


Per permettere ad altri sviluppare a fare da beta tester si puo' usare questo metodo

https://developer.amazon.com/it/blogs/post/Tx2EN8P2AHAHO6Y/How-to-Add-Beta-Testers-to-Your-Skills-Before-You-Publish

anche se non e' attualmente funzionante in Italia sembra che nel futuro il beta testing seguira' invece la procedura indicata da questo link

https://developer.amazon.com/it/blogs/alexa/post/42e7de5c-f7ef-4e3e-8391-c61fe24f6caa/improve-skill-quality-with-the-new-beta-testing-tool-for-alexa-skills-beta

IBM Netfinity 3000 alias Flip

La mia collezione si e' arricchita di un IBM Netfinity 3000, tecnicamente una workstation anche se e' stata usata nel tempo anche come server

Ho un legame particolare con questo computer perche' e' stato il mio primo computer di lavoro "serio" come amministratore di rete (il nome di rete della mia macchina era Flip, i nomi di rete derivavano tutti dalla Banda di Topolino)




Si tratta di PIII a 700 MHZ. La cosa pregevole (ed attualmente rara da ritrovare) e' la presenza di un disco di sistema SCSI)


Non ricordavo che le schede ISA fossero montate su una riser board ma ricordavo perfettamente quanto pesa il computer


Attualmente e' montato Windows NT 4.0 SP6 ma non so se montero' qualcosa di piu' recente


mercoledì 30 gennaio 2019

SMS + DeepSleep + Interrupt in Particle Electron

Prendendo spunto dal post precedente in questo caso l'SMS e' inviato da una Particle Electron generato da un interrupt su pin D2 (in questo caso pero' mandando il pin a GND) partendo pero' da una condizione di Deep Sleep

===============================================================
#include "application.h"
#include "cellular_hal.h"
STARTUP(cellular_credentials_set("TM", "", "", NULL));

const char* phNum = "+39347107xxxx";
const char* msg = "Interrupt fired";
int  ret;


void setup()
{
 pinMode(D7, OUTPUT);
 pinMode(D2, INPUT_PULLDOWN);    // sets pin as input
}

void loop()
    {
    digitalWrite(D7, HIGH);

    System.sleep(D2,FALLING);
    Cellular.on();
    Cellular.connect();
    delay(20000);
    if (Cellular.ready() == true)
    {
      ret = Cellular.command("AT+CMGF=1\r\n");
      ret = Cellular.command("AT+CMGS=\"%s%s\",129\r\n",(phNum[0] != '+') ? "+" : "", phNum); //
      ret = Cellular.command("%s\x1a", msg);
      digitalWrite(D7, LOW);
      delay(5000);

    }

}

Invio SMS da Particle Electron da interrupt

Come gestire gli interrupt fisici su Particle Electron ed inviare SMS
Al contratio di Arduino Uno sulla Electron ci sono molteplici pin che possono essere settati per ricevere un interrupt. In questo caso e' stato scelto il D2


Per atttivare l'interrupt viene mandata una corrente di 3.3V sul Pin D2 e viene settata una variabile volatile in modo che possa essere intercettata anche fuori dall'interrupt nella funzione loop. La gestione di invio inoltre non puo' essere gestita all'interno della funzione di interrupt

per la compilazione

particle compile electron interrupt.ino --saveTo interrupt.bin
particle flash --usb  interrupt.bin 

Nel video si osserva la procedura

----------------------------------------------------------------
#include "application.h"
#include "cellular_hal.h"
STARTUP(cellular_credentials_set("TM", "", "", NULL));

const char* phNum = "+3934710xxxxx";
const char* msg = "Interrupt fired";
int  ret;
volatile bool invio;

void  IN4_ISR() {
      invio = true;
}

void setup()
{
  invio = false;
 pinMode(D7, OUTPUT);
 pinMode(D2, INPUT_PULLDOWN);    // sets pin as input
 attachInterrupt(D2, IN4_ISR, FALLING);  //RISING, FALLING, CHANGE
}

void loop()
    {
      if (invio)
      {
        digitalWrite(D7, HIGH);
        ret = Cellular.command("AT+CMGF=1\r\n");
        ret = Cellular.command("AT+CMGS=\"%s%s\",129\r\n",(phNum[0] != '+') ? "+" : "", phNum); //
        ret = Cellular.command("%s\x1a", msg);
        invio = false;
        delay(500);
        digitalWrite(D7, LOW);
      }

}

martedì 29 gennaio 2019

Electron Particle e SIM Mobile Things

Dopo un po' di tempo ho ripreso in mano la Electron Sparkle ed ho montato una scheda SIM di Things Mobile. Nel tempo peraltro e' andata persa l'antenna originale della confezione prodotta da Taoglass ed il dispositivo non puo' funzionare senza... ho preso questa antenna su Amazon come sostituzione


Per configurare la scheda con una SIM di terze parti si deve installare la parte CLI di Particle con

npm install --unsafe-perm --verbose -g particle-cli

(attenzione potrebbero esserci problemi nella compilazione della seriale)

particle update

Per effettuare il flash del firmware si deve premere RESET+MODE, poi rilasciare RESET e tenendo premuto MODE attendere che il led diventi giallo

Si deve scaricare il file Tinker.ino modificando l'APN che per Mobile Things e' TM

#include "cellular_hal.h"
STARTUP(cellular_credentials_set("TM", "", "", NULL));
ed impostando il KeepAlive

Queste righe dovranno essere comprese in ogni script che verra' caricato sul dispositivo

si compila quindi
particle compile electron tinker.ino --saveTo firmware.bin
particle flash --usb firmware.bin


Puo' essere necessario effettuare il claim del device ma prima si deve conoscere il seriale
Per effettuare l'identify si deve premere il pusante Mode fino a quando il led diventa blu.
A questo punto si lancia

particle identify

Ci si logga sul cloud
particle cloud login

e si efffettua il claim
particle device add device_ID


Per verificare che tutto sia andato a buon fine si puo' provare ad accendere il led blu da linea di comando con il comando (dove Geocell e' il nome mnemonico del dispositivo)

particle call Geocell digitalwrite D7,HIGH

per l'invio degli SMS Mobile Things non ha problemi ed e' sufficiente il seguente codice
-----------------------------------------------
const char* phNum = "+39347107xxxxx";
const char* msg = "Test message";
int  ret;

void setup() {
Serial.begin(115200);
ret = Cellular.command("AT+CMGF=1\r\n");
Serial.print("Return from message format = ");
Serial.println(ret);
ret = Cellular.command("AT+CMGS=\"%s%s\",129\r\n",(phNum[0] != '+') ? "+" : "", phNum); //
Serial.print("Return from phNum send = ");
Serial.println(ret);
ret = Cellular.command("%s\x1a", msg);
Serial.print("Return from message send = ");
Serial.println(ret);

}


void loop() {

}
--------------------------------------------------



lunedì 28 gennaio 2019

Installazione Linux su IBM Netvista 8307

Questo piccolo IBM NetVista aveva bisogno di una nuova vita ricominciando da Linux....ma c'e' stato qualche problema. La macchina e' un P4 2.8GHz Single Core, 1 Gb Ram, 40 Gb HD


Il primo tentativo e' stato quello di effettuare un boot da USB Drive....niente da fare...il BIOS non supporta supporti USB...comprati e masterizzati DVD per procedere

La seconda sorpresa....il CPU non e' una x86-64. Ovviamente avevo masterizzato una Crunchbang 64 bit....via con il secondo download ed la seconda masterizzazione

Inizia l'installazione e kernel panic. Niente APIC....in fase di avvio bisogna avviare Grub di andare NoApic


Ennesimo riavvio e messaggio esoterico ..riavvio



a questo punto non riesce ad identificare il modo grafico giusto come avviare l'installazione (ero partito fiduciosamente per l'installer grafico)...Imposto il 311 ed inizia l'installazione


Formattazione del disco fisso e.....drive rotto. Basta non e' giornata...e per una macchina del genere non so quanto valga la pena cambiare HD....a proposito...anche il DVD Rom e' risultato non funzionante

Breakout Level Converter per Arduino

E' sempre piu' comune trovare elettronica a 3.3V e puo' succedere di doverla interfacciare con dispositivi a 5V...tipicamente una porta seriale

Per non friggere tutto si usano i level converter

Si collegano due tensioni di riferimento a 5V (su HV e GND) e 3.3 V (su LV e GND) e poi si possono usare i rimanenti pin (che corrispondono a 4 canali) per trasferire il segnale in modo bidirezionale dal pin superiore (per esempio HV1 canale 1 ad alto voltaggio) al pin inferiore (per esempio LV1 canale 1 basso voltaggio)


Testare un transistor con un multimetro

Per testare il transistor 2N2222A ho usato un tester ProKit MT-1210. Questo tester ha una predisposizione per cui si puo' misurare direttamente il valore di hFE ovvero il guadagno in corrente continua

Inserendo Emettitore, Base e Collettore nei rispettivi alloggiamenti e selezionando la funzione hFE si ottiene una lettura di 228 (le impostazioni di misura del multimetro sono 10 microA sul collettore ed una Vce di 2.8V a 20°C)




A questo punto si puo' andare a consultare la scheda tecnica del transistor. Il grafico e' basato su una Vce di 10 V
e' quindi verificato il funzionamento del transistor

Interruttore con transistor 2N2222A con Arduino

Invece di usare come al solito (e per comodita') un relay qui viene descritto come usare un transistor in funzione di interruttore. Il transistor in questione e' un 2N2222A (da non confondere con il P2N2222A dato che hanno la posizione dell'emettitore e del collettore invertiti)




Un pin digitale (il 13) e' collegato alla base del transistor per pilotare l'apertura o chiusura dell'interruttori (non dimenticarsi della resistenza)

Il transistor e' posizionato a valle dell'utilizzatore (qui semplificato con un led) ovvero sul lato GND

Si carica sull'Arduino lo sketch di esempio Blink

Ma perche' utilizzare un sistema cosi' complicato quando si potrebbe derivare la corrente dal pin13?? Perche' i pin digitali di Arduino possono erogare al massimo 45 mA e non possono quindi alimentare degli utilizzare piu' esigenti in termini di corrente

Per una trattazione piu' completa anche se introduttiva seguire questo link

venerdì 25 gennaio 2019

MKR1000 Sleep Mode con Interrupt da RTC

Ho ripreso in mano anche la MKR1000 per testare le capacita' di sleep mode in rapporto ad Arduino Uno. La MKR1000 ha un processore completamente differente (un SAMD21  per la precisione) e integra un RTC per cui non ha bisogno di supporto esterno



Un paio di annotazioni
1) La MKR1000 non ha un pulsante di accensione e l'unico modo di spengerla e' staccare la batteria. Cio' e' abbastanza fastidioso

2) In un caso ho perso il controllo della scheda perche' non si vedeva il device tra i dispositivi USB. In questi casi si deve premere in modo ravvicinato nel tempo per due volte il pulsante di reset

3) Per minimizzare il consumo si deve esplicitamente spengere il modulo Wifi, questa operazione non viene eseguita dallo standbymode

4) Le alimentazioni, quando e' presente la sola LiPo, sono a 3.3V. La porta a 5V in alimentazione output e' disponibile solo quando c'e' un cavo USB che alimenta dall'esterno

Il trucco per impostate il risveglio da RTC e' simile a quello visto in questo post. Si setta un'allarme ad una certa ora, poi all'interno del codice di interrupt si setta il nuovo allarme nel futuro. In questo esempio gli allarmi sono spostati nel tempo di un minuto

(il codice e' stato ripreso da questo link originario e leggermente migliorato per le mie esigenze)
----------------------------------------------

#include <RTCZero.h>

#include <WiFi101.h>


RTCZero rtc;

bool matched = false;
int alarmMinutes = 15;

/* Change these values to set the current initial time */
const byte seconds = 0;
const byte minutes = 14;
const byte hours = 14;

/* Change these values to set the current initial date */
const byte day = 25;
const byte month = 1;
const byte year = 19;

void setup()
{
  Serial.begin(9600);


  WiFi.end();



  rtc.begin();

  rtc.setTime(hours, minutes, seconds);
  rtc.setDate(day, month, year);

  rtc.setAlarmMinutes(alarmMinutes);
  
  rtc.enableAlarm(rtc.MATCH_MMSS);
  rtc.attachInterrupt(alarmMatch);
}

void loop()
{
  if (matched) {


    matched = false;
    printDate();
    printTime();
    Serial.println();
    delay(1000);
        
    alarmMinutes= (rtc.getMinutes()+1)%60;
    rtc.setAlarmMinutes(alarmMinutes);
    rtc.enableAlarm(rtc.MATCH_SS);
    rtc.attachInterrupt(alarmMatch);

    rtc.standbyMode();    // Sleep until next alarm match
  }
}

void alarmMatch()
{
  matched = true;
}

void printTime()
{
  print2digits(rtc.getHours());
  Serial.print(":");
  print2digits(rtc.getMinutes());
  Serial.print(":");
  print2digits(rtc.getSeconds());
  Serial.println();
}

void printDate()
{
  Serial.print(rtc.getDay());
  Serial.print("/");
  Serial.print(rtc.getMonth());
  Serial.print("/");
  Serial.print(rtc.getYear());
  Serial.print(" ");
}

void print2digits(int number) {
  if (number < 10) {
    Serial.print("0");
  }
  Serial.print(number);
}

Progetto Uno

Attenzione: per errore e' riportato che VCC del breakout di ADXL345 debba essere collegata a 5V mentre in realta' deve essere collegato a 3.3 V
----------------------------------------------------------------------
L'idea del progetto Uno e' avere un accelerometro che tramite un interrupt sveglia una Arduino Uno che tramite una radio per telemetria da droni invia un segnale ad un ricevitore remoto
Per risparmiare batteria il trasmettitore viene alimentato solo quando la Arduino si risveglia mediante un relay





I trasmettitori radio sono quelli indicati a questo link. Sono delle semplici radio che si comportano come delle seriali virtuali a 57600 e sono principalmente usati nell'ambito dei droni. Le radio vengono vendute a coppie per una comunicazione punto-punto ed una (o entrambe) hanno un connettore USB piu' un connettore a 6 pin...visto che vengono venduti per droni hanno dei cavi gia' predisposti per PixHawk o simili in alcuni casi e' difficile adattare i cavi per Arduino in modo semplice..se ne trovano alcuni come quello in foto che permettono l'inserimento dei pin




--------------------------------------------------------------------------

/*  *********************************************
 *  SparkFun_ADXL345_Example
 *  Triple Axis Accelerometer Breakout - ADXL345 
 *  Hook Up Guide Example 
 *  
 *  Utilizing Sparkfun's ADXL345 Library
 *  Bildr ADXL345 source file modified to support 
 *  both I2C and SPI Communication
 *  
 *  E.Robert @ SparkFun Electronics
 *  Created: Jul 13, 2016
 *  Updated: Sep 06, 2016
 *  
 *  Development Environment Specifics:
 *  Arduino 1.6.11
 *  
 *  Hardware Specifications:
 *  SparkFun ADXL345
 *  Arduino Uno
 *  *********************************************/

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

ADXL345 adxl = ADXL345();             // USE FOR I2C COMMUNICATION


int interruptPin = 2;                 // Setup pin 2 to be the interrupt pin (for most Arduino Boards)
const int wakeUpPin = 2;                //For good accelaration return values I comment out this

void wakeUp()
{

}

void setup(){
  
  Serial.begin(57600);                 // Start the serial terminal
  Serial.flush();

  pinMode(7, OUTPUT);

  
  adxl.powerOn();                     // Power on the ADXL345
  adxl.setRangeSetting(2);           // 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, 1, 1);       // 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, 1, 1);     // 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
  pinMode(wakeUpPin, INPUT); 

}

void loop(){

    attachInterrupt(0, wakeUp, RISING);
   
    int x,y,z;   
  adxl.readAccel(&x, &y, &z);         // Read the accelerometer values and store them in variables declared above x,y,z

  digitalWrite(7, HIGH);
  delay(500);
  
  Serial.print(x);
  Serial.print(", ");
  Serial.print(y);
  Serial.print(", ");
  Serial.println(z); 

  digitalWrite(7, LOW);

  
  ADXL_ISR();
}

void ADXL_ISR() {
  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.flush();        
              adxl.InactivityINT(0);
              LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
  }
  
  // Activity
  if(adxl.triggered(interrupts, ADXL345_ACTIVITY)){
    Serial.println("*** ACTIVITY ***"); 
     
     adxl.InactivityINT(1);
     //add code here to do when activity is sensed
  }
  
  // Double Tap Detection
  if(adxl.triggered(interrupts, ADXL345_DOUBLE_TAP)){
    Serial.println("*** DOUBLE TAP ***");
     adxl.InactivityINT(1);
     //add code here to do when a 2X tap is sensed
  }
  
  // Tap Detection
  if(adxl.triggered(interrupts, ADXL345_SINGLE_TAP)){
    Serial.println("*** TAP ***");
    adxl.InactivityINT(1);
  } 
}

void blink() { 
}

Progetto Zero

GPS ad alimentazione solare con registrazione dati su SD Card e sleep mode ed attivazione programmabile tramite orologio interno

Componenti:
Arduino Uno
SeedStudio Solar Charger Shield
Data recoder shield
RTC DS3231
GPS con uscita seriale
Lipo 10.000 mAh
Pannello solare 6V
SD Card 2Gb



Il rele' deve essere collegato nella configurazione NA (normalmente aperto)
La seriale del GPS e' collegata direttamente alla seriale dell'Arduino perche' usare una SoftwareSerial crea problemi con la modalita' Sleep

Tra i vari aggiustamenti che ho fatto al programma c'e' anche un ridimensionamento dell'array del buffer. Con un buffer da 200 byte il programma si compilava, veniva lanciato su Arduino ma la IDE segnalava che il poco spazio di memoria rimasto libero (un centinaio di bytes) poteva rendere il programma instabile....in effetti durante l'esecuzione il buffer veniva riempito con caratteri a caso e con pezzi della memoria. Ridimensionato il buffer il problema e' scomparso
------------------------------------------------------------------------------
#include <RTClibExtended.h>
#include <Wire.h>
#include <LowPower.h>

#include <stdlib.h>
#include <avr/interrupt.h>      // library for interrupts handling
#include <avr/sleep.h>          // library for sleep
#include <avr/power.h>          // library for power control

// SD Card headers
#include <SPI.h>
#include <SD.h>



#define wakePin 2    //use interrupt 0 (pin 2) and run function wakeUp when pin 2 gets LOW

RTC_DS3231 rtc;      //we are using the DS3231 RTC


int contatore;
const unsigned int dim_buffer = 100;
int SerialData[dim_buffer];


const int chipSelect = 10;
char incomingByte = 0;   // for incoming serial data

char filen[10];
String filename;
char filenb[10];
String filenameb;


DateTime now;


//-------------------------------------------------

void wakeUp()
{


}

//------------------------------------------------------------

void setup() {


  pinMode(7, OUTPUT);
  

  delay(3000);
  // Inizializzazione SD
  if (!SD.begin(chipSelect)) {
    //Serial.println("Card failed, or not present");
    while (1);   

    //if (!sd.begin(chipSelect)) {
    //Serial.println("Card failed, or not present");
    //while (1);    Serial.begin(9600);

  }

  delay(3000);

  //Set pin D2 as INPUT for accepting the interrupt signal from DS3231
  pinMode(wakePin, INPUT);;

  //Initialize communication with the clock
  Wire.begin();
  rtc.begin();
  rtc.adjust(DateTime(__DATE__, __TIME__));   //set RTC date and time to COMPILE time
  delay(500);
  now = rtc.now();


  //clear any pending alarms
  rtc.armAlarm(1, false);
  rtc.clearAlarm(1);
  rtc.alarmInterrupt(1, false);
  rtc.armAlarm(2, false);
  rtc.clearAlarm(2);
  rtc.alarmInterrupt(2, false);

  rtc.writeSqwPinMode(DS3231_OFF);
  delay(1000);

}

//------------------------------------------------------------

void loop() {
   Serial.begin(9600);
    while (!Serial) {
  }
 
  Serial.println("inizio");

  digitalWrite(7, HIGH);


  now = rtc.now();
  sprintf(filen, "%02d%02d%02d%02d.txt", now.month(), now.day(), now.hour(), now.minute());
  String filename(filen);
  delay(2500);

  Serial.println(filename);


  File dataFile = SD.open(filename, FILE_WRITE);


  for (uint32_t i = 0; i <= 4000; i++) {
    contatore = 0;
    while (contatore < 98)
    {
      if (Serial.available() > 0) {
        SerialData[contatore] = Serial.read();
        //dataFile.print(char(Serial.read()));
        contatore++;

        //Serial.print(char(SerialData[contatore-1]));
        //dataFile.print(" ");
        //Serial.println(contatore);
      }

    }
    

    if (dataFile) {
      for (int s = 0; s < contatore - 1; s++) {
        Serial.print(SerialData[s]);
        Serial.print("  ");
        Serial.print(char(SerialData[s]));
        if (SerialData[s] != 255) {
                dataFile.print(char(SerialData[s]));
                Serial.println("  I");               
                }
                else
                {
                  Serial.println("E");
                
                }
        }
      }
    

    //dataFile.write(SerialData,197);
    memset(SerialData,0,sizeof(SerialData));

  }
  dataFile.close();
  Serial.println("Finito");

  // salva la tensione della batteria
  sprintf(filenb, "%02d%02d%02d%02d.bat", now.month(), now.day(), now.hour(), now.minute());
  String filenameb(filenb);

  File dataFileb = SD.open(filenameb, FILE_WRITE);
  if (dataFileb) {
    String bat = String(analogRead(A0), DEC);
    dataFileb.println(bat);
    dataFileb.close();
  }

  // spenge antenna GPS
  Serial.end();
  digitalWrite(7, LOW);
  delay(500);

  now = rtc.now();
  DateTime nextAlarm = now + TimeSpan(0, 4, 0, 0);


  delay(3000);
  rtc.setAlarm(ALM1_MATCH_HOURS, nextAlarm.minute(), nextAlarm.hour(), nextAlarm.second());   //set your wake-up time here
  rtc.alarmInterrupt(1, true);
  delay(3000); // wait for console
  attachInterrupt(0, wakeUp, LOW);       //use interrupt 0 (pin 2) and run function wakeUp when pin 2 gets LOW
  LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);   //arduino enters sleep mode here
  detachInterrupt(0);                                    //execution resumes from here after wake-up
  //When exiting the sleep mode we clear the alarm
  rtc.armAlarm(1, false);
  rtc.clearAlarm(1);
  rtc.alarmInterrupt(1, false);

  delay(3000);

}

giovedì 24 gennaio 2019

Wakeup Arduino da interrupt con ADXL345

Attenzione: per errore e' riportato che VCC del breakout di ADXL345 debba essere collegata a 5V mentre in realta' deve essere collegato a 3.3 V
----------------------------------------------------------------------

Questo post e' il gemello del precedente utlizzando pero' ADXL345
Il codice e' stato completamente ripreso da questo post 




Ho rimosso un po' di linee per rendere il codice piu' leggibile

In pratica se viene generato un interrupt di Inactivity l'arduino va in sleep. L'ADXL345 e' settato alla massima sensibilita' con una soglia di 75 ed un tempo prima di considerarsi inattivo di 3 secondi

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

ADXL345 adxl = ADXL345();             // USE FOR I2C COMMUNICATION


int interruptPin = 2;                 // Setup pin 2 to be the interrupt pin (for most Arduino Boards)
const int wakeUpPin = 2;                //For good accelaration return values I comment out this

void wakeUp()
{

}

void setup(){
  
  Serial.begin(9600);                 // Start the serial terminal
  Serial.flush();
  
  adxl.powerOn();                     // Power on the ADXL345
  adxl.setRangeSetting(2);           // 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, 1, 1);       // 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, 1, 1);     // 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(3);         // 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
  pinMode(wakeUpPin, INPUT); 

}

void loop(){

    attachInterrupt(0, wakeUp, RISING);
  int x,y,z;   
  adxl.readAccel(&x, &y, &z);       

  Serial.print(x);
  Serial.print(", ");
  Serial.print(y);
  Serial.print(", ");
  Serial.println(z); 
  
  ADXL_ISR();
}

void ADXL_ISR() {
  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.flush();        
              adxl.InactivityINT(0);
              LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
  }
  
  // Activity
  if(adxl.triggered(interrupts, ADXL345_ACTIVITY)){
    Serial.println("*** ACTIVITY ***"); 
     
     adxl.InactivityINT(1);
     //add code here to do when activity is sensed
  }
  
  // Double Tap Detection
  if(adxl.triggered(interrupts, ADXL345_DOUBLE_TAP)){
    Serial.println("*** DOUBLE TAP ***");
     adxl.InactivityINT(1);
     //add code here to do when a 2X tap is sensed
  }
  
  // Tap Detection
  if(adxl.triggered(interrupts, ADXL345_SINGLE_TAP)){
    Serial.println("*** TAP ***");
    adxl.InactivityINT(1);
  } 
}

void blink() { 
}