Controllo LCD array con RTC (con sorgenti) - LCD control array with RTC (with sources)

Prova di gestione di un economico array di LCD a matrice 8x8 con lettura di un modulo RTC. I moduli a matrice LCD che ho preso sono già raggruppati a 4 e possono essere connessi altri moduli in cascata sia in senso orizzontale che verticale. La libreria utilizzata si serve della connessione SPI (Serial Peripheral Interface) per la gestione dei moduli mentre il modulo RTC usa la I2C. In internet si trovano più facilmente moduli 8x8 singoli ma questi già assemblati a 4 sono veramente comodi anche perchè sono separabili o collegabili in serie con facilità. Lo sketch gira sul Nano ma dovrebbe andare bene su tutti gli Arduini, semmai controllare la corrispondenza dei segnali sui piedini. Le librerie potete trovarle utilizzando la ricerca automatica della IDE oppure su GitHub.


Test of control of an economic array of LCD 8x8 matrix with reading a RTC module. The LCD matrix modules that I took are already grouped in 4 and can be connected to other modules in cascade, both horizontally and vertically. The library used uses the SPI connection (Serial Peripheral Interface) for module management and the RTC module uses I2C. In the Internet there are more easily individual 8x8 modules but these already assembled to 4 are also really comfortable because they are separable or connected in series with ease. The sketch runs on Nano but should be fine on all Arduini, if anything, check the correspondence of the signals on the pins. Libraries you can find them using automatic search of the IDE or on GitHub.




Dettaglio della connessione tra i singoli moduli.
The detail of the connection between the individual modules.


Il modulo acceso, molto luminoso.
The module turned on, very bright


// ***********************************
// Test Controllo LCD array con RTC
// Reteservizi di Paolo Fiaschi
// 2016
// ***********************************

#include 
#include 
#include 
#include 
#include "RTClib.h"

// ************************************
// connessione modulo LED<->Arduino
/*
VCC<->5V
GND<->GND
DIN<->D11
CS <->D10
CLK<->D13
*/

// connessione modulo RTC<->Arduino
/*
VCC<->5V
GND<->GND
SDA<->A4
SCL<->A5
*/

// ************************************
int pinCS = 10; // Attach CS to this pin, DIN to MOSI and CLK to SCK (cf http://arduino.cc/en/Reference/SPI )
int numberOfHorizontalDisplays = 4; // numero display in orizzontale
int numberOfVerticalDisplays = 1;   // numero display in verticale

Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays);

RTC_DS1307 RTC;

String tape = "Scritta scorrevole...";
int wait = 30; // velocità di scorrimento in milliseconds

int spacer = 1;
int width = 5 + spacer; // 5 pixel di larghezza font

// senza spazi per presentarlo da solo
String mesi[] = {" gen "," feb "," mar "," apr "," mag "," giu "," lug "," ago "," set "," ott "," nov "," dic "};
// senza spazi per presentarlo attaccato alla data
String mesi1[] = {"gen","feb","mar","apr","mag","giu","lug","ago","set","ott","nov","dic"}; 


// *******************************************
void setup() {

  Serial.begin(9600);

  // *** init RTC
  Wire.begin();
  RTC.begin();

  // **************
  // settaggio RTC
  // **************
  //If we remove the comment from the following line, we will set up the module time and date with the computer one
  //RTC.adjust(DateTime(__DATE__, __TIME__));

  matrix.setIntensity(7); // luminosità da 0 a 15

  // impostazione del n. del display utilizzato e delle sue caratteristiche di visualizzazione
  // vedi le specifiche della libreria Max72xxPanel

  // Imposta le proprieta di ogni display
  matrix.setPosition(0, 0, 0); // The first display is at <0, 0>
  //  matrix.setPosition(1, 1, 0); // The second display is at <1, 0>
  //  matrix.setPosition(2, 2, 0); // The third display is at <2, 0>
  //  matrix.setPosition(3, 3, 0); // And the last display is at <3, 0>
  //  ...
  matrix.setRotation(0, 1);    // Rovescia la visualizzazione del n display
  matrix.setRotation(1, 1);    // Rovescia la visualizzazione del n display
  matrix.setRotation(2, 1);    // Rovescia la visualizzazione del n display
  matrix.setRotation(3, 1);    // Rovescia la visualizzazione del n display

  // test:accende un pixel alla locazione 0,0 e uno alla 32,7
  /*
  matrix.fillScreen(LOW);
  matrix.drawPixel(0, 0, HIGH);
  matrix.drawPixel(32, 7, HIGH);  
  matrix.write();
  */

  // recupera la data
  DateTime now = RTC.now();
}

// *************************************
void loop() {

  // presenta la scritta scorrevole.
  StringScroll(tape);

  // recupera la data
  DateTime now = RTC.now();

  //mostra la l'ora
  //String ora=now.hour()+":"+now.minute();

  char buf[5];
  sprintf(buf, "%02d:%02d", now.hour(), now.minute());
  
  StringStatic(buf,2000);
  //StringStatic((String)now.hour()+":"+(String)now.minute(),2000);
  
  //mostra la la data
  //StringStatic((String)now.day()+" ",2000); // giorno da solo
  StringStatic((String)now.day()+mesi1[now.month()],2000);  // giorno insieme al mese
  StringStatic((String)now.year(),2000);
}

// ************************************
// visualizza la stringa scorrevole sul display
void StringScroll(String stringa) {
  for ( int i = 0 ; i < width * stringa.length() + matrix.width() - 1 - spacer; i++ ) {

    matrix.fillScreen(LOW);

    int letter = i / width;
    int x = (matrix.width() - 1) - i % width;
    int y = (matrix.height() - 8) / 2;

    while ( x + width - spacer >= 0 && letter >= 0 ) {
      if ( letter < stringa.length() ) {
        matrix.drawChar(x, y, stringa[letter], HIGH, LOW, 1);
      }

      letter--;
      x -= width;
    }

    matrix.write(); // Send bitmap to display

    delay(wait);
  }
}

// ************************************
// visualizza la stringa statica sul display per il tempo richiesto
void StringStatic(String stringa, int tempo) {

  matrix.fillScreen(LOW);
  
  for ( int i = 0 ; i < width * stringa.length() + matrix.width() - 1 - spacer; i++ ) {
    int letter = i / width;
    int x = (matrix.width() - 1) - i % width;
    int y = (matrix.height() - 8) / 2;

    while ( x + width - spacer >= 0 && letter >= 0 ) {
      if ( letter < stringa.length() ) {
        matrix.drawChar(x, y, stringa[letter], HIGH, LOW, 1);
      }

      letter--;
      x -= width;

      if (letter==stringa.length()-1) break;
    }
  }
  matrix.write(); // Send bitmap to display
  delay(tempo);
}

// *********************************
// ricompone i dati dell'RTC in un unico buffer
String ConvData(DateTime Data) {
  char buf[30];
  sprintf(buf, "%02d/%02d/%04d %02d:%02d:%02d", Data.day(), Data.month(), Data.year(), Data.hour(), Data.minute(), Data.second());

  return buf;
}


Acquisizione rotazione encoder (con sorgenti) - rotary encoder acquisition (with sources)

Gestione della rotazione di un encoder con verifica dello stato di fermo e della direzione di rotazione. Utilizza gli interrupt per agganciare la ricezione degli impulsi di rotazione.


Sull'encoder ho calettato un motorino per fare dei test sulla velocita di acquisizione.
Per ogni unità di tempo l'Arduino invia il numero di impulsi, positivi o negativi, ricevuti dall'ultima lettura.
 L'RTC serve per loggare l'impulso con il time.


// Comment
// ***********************************
// Test Lettura Encoder con logger video
// Reteservizi di Paolo Fiaschi
// 2016
// ***********************************

#include 
#include 
#include "RTClib.h"

RTC_DS1307 rtc;
elapsedMillis timeElapsed; 

DateTime now;

const int BUFFSIZE = 20; // dimensioni buffer
char buffer[BUFFSIZE];   // buffer per la ricezione dalla seriale

String Buff = "";
boolean codeValid = false;
boolean debug = false;      

unsigned long previousMillis = 0;        

unsigned int interval = 2000;           // timeout della ricezione dati seriale
unsigned long currentMillis;
unsigned long Contatore=0;
 
int encoderPin1 = 2;
int encoderPin2 = 3;
int ledLeftPin  = 5;
int ledRightPin = 6;
int ledStopPin  = 7;
int ledAlarmPin  = 8;

int Direzione=0;

volatile int lastEncoded = 0;
volatile long encoderValue = 0;
volatile long localEncoderValue = 0;

long lastEncoderValue = 0;
long checkEncoderValue= 0;

int lastMSB = 0;
int lastLSB = 0;

// ******************************************** 
void setup() {
  Serial.begin (115200);
  
  // *** init RTC
  Wire.begin();
  rtc.begin();

  // **************
  // settaggio RTC
  // **************
  if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }
  // ***
 
  pinMode(encoderPin1, INPUT);
  pinMode(encoderPin2, INPUT);
  pinMode(ledLeftPin, OUTPUT);
  pinMode(ledRightPin,OUTPUT);
  pinMode(ledStopPin, OUTPUT);
  pinMode(ledAlarmPin, OUTPUT);
  
  digitalWrite(encoderPin1, HIGH); //turn pullup resistor on
  digitalWrite(encoderPin2, HIGH); //turn pullup resistor on

  // interrupt agganciati sul cambio di stato delle porte
  attachInterrupt(0, updateEncoder, CHANGE);
  attachInterrupt(1, updateEncoder, CHANGE);
}

// ********************************************** 
void loop(){
  // la lettura dell'encoder viene fatta dagli interrupt.

  if (timeElapsed > interval) {
    // errore timeout
    //if(debug) Serial.println("Errore Timeout Comunicazione");
    digitalWrite(ledAlarmPin,HIGH);
  }
 
  if (Serial.available() > 0) 
  {
    timeElapsed = 0;
    digitalWrite(ledAlarmPin,LOW);
    
    int index=0;
    //delay(10); // aspetta si riempia il buffer (non serve per 1 solo carattere)
    
    int numChar = Serial.available();
    
    if (numChar > BUFFSIZE) numChar = BUFFSIZE;
    
    while (numChar--) {
      buffer[index++] = Serial.read();
    }
    splitString(buffer); // Elabora la stringa ricevuta
  }

  // gestione indicatori di direzione
  if(lastEncoderValue==localEncoderValue) Direzione=0;

  if(Direzione==0) {
    digitalWrite(ledLeftPin,LOW);
    digitalWrite(ledRightPin,LOW);
    digitalWrite(ledStopPin,HIGH);
  }
  
  if(Direzione==1) {
    digitalWrite(ledLeftPin,HIGH);
    digitalWrite(ledRightPin,LOW);
    digitalWrite(ledStopPin,LOW);
  }

  if(Direzione==2) {
    digitalWrite(ledLeftPin,LOW);
    digitalWrite(ledRightPin,HIGH);
    digitalWrite(ledStopPin,LOW);
  }

  lastEncoderValue=localEncoderValue;
  
  delay(5); // serve solo per dare tempo ai led di accendersi.
}

// ***************************************** 
void updateEncoder(){
  int MSB = digitalRead(encoderPin1); //MSB = bit + significativo
  int LSB = digitalRead(encoderPin2); //LSB = bit - significativo
 
  int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number
  int sum  = (lastEncoded << 2) | encoded; //adding it to the previous encoded value
 
  if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) {
    encoderValue ++; Direzione=1;
    
    if(encoderValue>200000) { // per evitare l'overflow
      encoderValue=1;
      lastEncoderValue=0; 
    }
  }
  if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) {
    encoderValue --; Direzione=2;
  
    if(encoderValue<-200000 and="" ata="" break="" buff.concat="" buffer="" buffers="" c="Check" caratteri="" case="" char="" check="" clear="" codevalid="true;" command="" commands="" converte="" data="ConvData(now);" de-tokenize="" debug="" do="" e="Encoder" each="" encodervalue="" entered:="" erial.println="" evitare="" for="" from="" i="" if="" in="" int="" l="" lastencoded="encoded;" lastencodervalue="0;" list="" localencodervalue="encoderValue;" next="" now="" null="" ontatore="" onvdata="" overflow="" parameter="strtok" parse="" parsecmd="" pass="" per="" processed="" received="" remove="" result="" ricevuti="" sequentially="" serial.flush="" serial.print="" serial.println="" serial="" splitstring="" store="" stringa="" switch="" text="" the="" this="" time="" to="" tring="" value="" void="" while="" x="">2000000000) Contatore=0; // resetta il long
      
      Serial.print(++Contatore);
      Serial.print("-");
      
      Serial.println(encoderValue);
      encoderValue=0; // una volta inviato il valore lo azzera per ripartire
      codeValid = true;
      break;

    case ('T'): //check T=Timer
      switch(data[1])
      {
        case('T'):  // Time (TT)
          now = rtc.now();  
          Serial.println(ConvData(now));      
          codeValid = true;
          break;

        case('S'):  // Time setting xxddmmyyyyhhmmss (TS)
          String str(data);
          if(str.length()==18) {  // ci sono anche i CRLF
            String anno=str.substring(6,10);
            String mese=str.substring(4,6);
            String giorno=str.substring(2,4);
            String ora=str.substring(10,12);
            String minuti=str.substring(12,14);
            String secondi=str.substring(14,16);
            
            rtc.adjust(DateTime(anno.toInt(), mese.toInt(), giorno.toInt(), ora.toInt(), minuti.toInt(), secondi.toInt()));
            
            now = rtc.now();  
            //Serial.print("Nuova Data:"); 
            Serial.println(ConvData(now));      
            codeValid = true;
          }
          break;
      }      
   
    default:
      if(debug)
      {
        Serial.println(data); 
      }
    }
  
  //if(codeValid) Serial.println(buffer); //echo back what is received
  codeValid = false;
  Buff = ""; //Reset passing string
}  

// *********************************
String ConvData(DateTime Data) {

/*    
String result="";

char buffer[30];
PString str(buffer, sizeof(buffer));
str = Data.day(); // assignment
str += "/";
str += Data.month(); // concatenation
str += "/";
str += Data.year(); // concatenation
str += " ";
str += Data.hour(); // concatenation
str += ":";
str += Data.minute(); // concatenation
str += ":";
str += Data.second(); // concatenation
*/

char buf[30];
sprintf(buf, "%02d/%02d/%04d %02d:%02d:%02d",Data.day(), Data.month(), Data.year(), Data.hour(), Data.minute(), Data.second()); 
 
return buf;
}