Orologio

Buongiorno a tutti, nelle scorse settimane mi sono costruito un orologio (ore/minuti) con 4 display a 7 segmenti con i seguente programma:

// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
#include "RTClib.h"
#include <SevSeg.h>
#include <stdio.h>
#include <DS1302.h>

RTC_DS1307 rtc;
SevSeg sevseg; //Instantiate a seven segment controller object
int OreMin ;
int secOra;
byte decPlace;

char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

void setup () {
  Serial.begin(9600);
  Serial.println("Versione caricata Prova_tiny_02");

  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  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(2020, 9, 16, 9, 9, 0));

  byte numDigits = 4;
  byte digitPins[] = {13, 12, 11, 10};
  byte segmentPins[] = {2, 3, 4, 5, 6, 7, 8, 9}; //Segments: A,B,C,D,E,F,G,Period
  bool resistorsOnSegments = false; // 'false' means resistors are on digit pins
  byte hardwareConfig = COMMON_CATHODE;
  bool updateWithDelays = false; // Default 'false' is Recommended
  bool leadingZeros = true; // Use 'true' if you'd like to keep the leading zeros
  bool disableDecPoint = false; // Use 'true' if your decimal point doesn't exist or isn't connected

  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments,
               updateWithDelays, leadingZeros, disableDecPoint);
  sevseg.setBrightness(10);
}

void printTime() {
  DateTime now = rtc.now();
  OreMin = (now.hour() * 100) + now.minute();
  secOra = (now.second()); // rilevo i secondi da RTC
}

void loop () {

  printTime(); // rileva l'orario
  // faccio lampeggiare il punto separatore ore/minuti
  if ((secOra % 2) == 0) {
    sevseg.setNumber(OreMin);
  } else {
    decPlace = 2;
    sevseg.setNumber(OreMin, decPlace);
  }
  sevseg.refreshDisplay();
}

Ora mi è venuta l'idea balzana di aggiungere altri 2 display per visualizzare anche i secondi.

Devo quindi avere non un puntino separatore ma due. L'unica idea che ho è di cercare di comandare questi separatamente collegandoli ad un PIN da mantenere sempre HIGH.

Mi sembra un'idea brutale e poco elegante (e non ho ancora provato se funzionerebbe!); qualcuno può suggerirmi una soluzione migliore?

Grazie

Enrico

Basterebbe farti da solo la funzione di scrittura e multiplexing su misura, anziché dover faticare per far fare alla libreria ciò che vuoi tu! :slight_smile:

Bravo! .... pensi che non ci abbia già provato?

Grazie! ... e quale è stato l'esito?

Più che parlare di un esito non ho idea da dove cominciare, da buon chimico ho cercato di capire come funziona la SevSeg ma non sono stato capace di trovare il listato!

So che dovrei modificare il comando di accensione dei segmenti CP, basterebbe quindi solo sostituire uno 0 con un 1 .... ma dove sono?

Ora sto cercando di capire come funziona un multiplexing per cercare di costruire qualcosa ad hoc.

Enrico

Leggi il mio messaggio n.3, in particolare i miei messaggi nell'ultimo link:
https://forum.arduino.cc/?topic=690709#msg4652116

Bene, GRAZIE, ho imparato l'utilizzo del PORTD (i segmenti), per il PORTB (i display) penso ci vorrà ancora altro tempo per ora mi barcameno utilizzando LOW/HIGH.

In settimana spero di trovare il tempo di passare alla fase di costruzione con i 6 display ed iniziare a cercare di trasferire l'ora su questi.

Ancora grazie, Enrico

Prego :slight_smile:

Buongiorno a tutti,
riprendo la discussione in quanto non riesco ad utilizzare correttamente i PIN di "PORTD".

Utilizzo un arduino nano per pilotare dei display a 7 segmenti, devo quindi utilizzare i PIN 0 ed 1 (RX e TX). Questi, però rimangono sempre accesi anche se con una luminosità inferiore.

Il programma utilizzato è il seguente:

// Example sketch for interfacing with the DS1302 timekeeping chip.
#include <stdio.h>
#include <DS1302.h>


long num = 0; // vaore di 6 cifre da scomporre
long num1 ;
long num2 ;
long num3 ;
long num4 ;
long num5 ;
long num6 ;


long v_sec;
long v_min;
long v_hr;


byte values[] = {
  //hgfedcba
  B10111111, // 0  -0
  B10000110, // 1  -1
  B11011011, // 2  -2
  B11001111, // 3  -3
  B11100110, // 4  -4
  B11101101, // 5  -5
  B11111101, // 6  -6
  B10000111, // 7  -7
  B11111111, // 8  -8
  B11101111, // 9  -9
};


namespace {


const int kCePin   = A0;  // Chip Enable
const int kIoPin   = A1;  // Input/Output
const int kSclkPin = A2;  // Serial Clock


// Create a DS1302 object.
DS1302 rtc(kCePin, kIoPin, kSclkPin);


void printTime() {
  // Get the current time and date from the chip.
  Time t = rtc.time();
  v_hr = t.hr;
  v_min = t.min;
  v_sec = t.sec;


  num = ((v_hr * 10000) + (v_min * 100) + v_sec);
}


}  // namespace


void setup() {
  Serial.begin(9600);
  Serial.println("Prove_clock/prova_04");


  DDRD = B11111111;
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);


  //rtc.writeProtect(false);
  //rtc.halt(false);


  //Time t(2020, 10, 3, 17, 38, 00, Time::kSaturday);


  //rtc.time(t);
}


void loop() {
  printTime();
  numero();
  digitalWrite(8, HIGH);
  digitalWrite(9, HIGH);
  digitalWrite(10, HIGH);
  digitalWrite(11, HIGH);
  digitalWrite(12, HIGH);
  digitalWrite(13, LOW);
  PORTD = values[num1];
  delay (3);


  digitalWrite(8, HIGH);
  digitalWrite(9, HIGH);
  digitalWrite(10, HIGH);
  digitalWrite(11, HIGH);
  digitalWrite(12, LOW);
  digitalWrite(13, HIGH);
  PORTD = values[num2];
  delay (3);


  digitalWrite(8, HIGH);
  digitalWrite(9, HIGH);
  digitalWrite(10, HIGH);
  digitalWrite(11, LOW);
  digitalWrite(12, HIGH);
  digitalWrite(13, HIGH);
  PORTD = values[num3];
  delay (3);


  digitalWrite(8, HIGH);
  digitalWrite(9, HIGH);
  digitalWrite(10, LOW);
  digitalWrite(11, HIGH);
  digitalWrite(12, HIGH);
  digitalWrite(13, HIGH);
  PORTD = values[num4];
  delay (3);


  digitalWrite(8, HIGH);
  digitalWrite(9, LOW);
  digitalWrite(10, HIGH);
  digitalWrite(11, HIGH);
  digitalWrite(12, HIGH);
  digitalWrite(13, HIGH);
  PORTD = values[num5];
  delay (3);


  digitalWrite(8, LOW);
  digitalWrite(9, HIGH);
  digitalWrite(10, HIGH);
  digitalWrite(11, HIGH);
  digitalWrite(12, HIGH);
  digitalWrite(13, HIGH);
  PORTD = values[num6];
  delay (3);
}


void numero() {
  num6 = (num / 100000);
  num5 = ((num - (num6 * 100000)) / 10000);
  num4 = ((num - (num6 * 100000) - (num5 * 10000)) / 1000);
  num3 = ((num - (num6 * 100000) - (num5 * 10000) - (num4 * 1000)) / 100);
  num2 = ((num - (num6 * 100000) - (num5 * 10000) - (num4 * 1000) - (num3 * 100)) / 10);
  num1 = ((num - (num6 * 100000) - (num5 * 10000) - (num4 * 1000) - (num3 * 100) - (num2 * 10)));


}

Qualcuno può indicarmi dove sbaglio?
Saluti
Enrico

enrico24:
Mi sembra un'idea brutale e poco elegante (e non ho ancora provato se funzionerebbe!); qualcuno può suggerirmi una soluzione migliore?

Grazie, Enrico

Per me invece è la soluzione migliore. Perchè complicarsi la vita? La libreria fa quasi tutto.
Tra l'altro nell'ultimo tuo esempio mischi manipolazione diretta dei pin con i comandi Arduino.
Mi pare ti stai incasinando... per un puntino ? Per me meglio la tua idea di metterlo sempre a high. Anzi meglio se lampeggia come l'altro puntino.

Ma tu attualmente hai 4 sevensegment o 1 sevensegment a 4 cifre ?

Nid, permettimi di farti notare che la frase che hai riportato non fa capire assolutamente a che cosa tu ti stia riferendo: non si capisce quale è l'idea brutale...

Enrico, ciò che dici potrebbe accadere per due ragioni:

  1. Le porte sono impostate come ingressi, ma non è questo il caso.
  2. Le cifre visualizzate vengono cambiate velocissimamente, per cui appaiono sovrapposte, visualizzando un 8...
    Uhmm...

Vedo, comunque, che hai complicato un po' l'estrazione delle cifre: a che serve comporre num? Basta estrarre num1 e num2 dalle ore, num3 e num4 dai minuti e num5 e num6 dai secondi.
Gli I/O 8...13, poi, sono la porta B, quindi anche qui puoi usare PORT:

  digitalWrite(8, HIGH);
  digitalWrite(9, HIGH);
  digitalWrite(10, HIGH);
  digitalWrite(11, HIGH);
  digitalWrite(12, HIGH);
  digitalWrite(13, LOW);

equivale a un semplice PORTB &= 0b11011111; PORTB |= 0b00011111;
Continua così: è un bell'esercizio che ti sarà utile. Inoltre, più ti svincoli dalle librerie, più stai tranquillo che, se un giorno andrai a modificare e ricompilare il programma, non avrai problemi dovuti all'uso di una libreria che è stata aggiornata con qualche modifica nell'uso (purtroppo capita...). L'ideale sarebbe poter salvare (o esportare) il progetto completo delle librerie utilizzate...

Ma tu attualmente hai 4 sevensegment o 1 sevensegment a 4 cifre ?

A dir la verità ho 6 sevensegment a 1 cifra (per visualizzare anche i secondi); nel programma che utilizza la libreria SevSeg ho piegato alcuni piedini dei puntini per separare ore/minuti/secondi. E questa funziona perfettamente.

A puro scopo didattico (ho tanto da imparare!) ho sviluppato il programma senza librerie che ho postato.

  1. Le cifre visualizzate vengono cambiate velocissimamente, per cui appaiono sovrapposte, visualizzando un 8..

Le cifre vengono visualizzate correttamente, solo i segmenti A e B rimangono sempre accesi anche se con una luminosità inferiore.
Tra l'altro anche i 4 led interni del nano (RX, TX, POW e L) rimangono sempre accesi

Gli I/O 8...13, poi, sono la porta B, quindi anche qui puoi usare PORT

Esatto, era esattamente quello che mi proponevo di fare una volta risolto il problema dei PIN 0 e 1 (relativi ai segmento A e B).

Saluti
Enrico

A dir la verità ho 6 sevensegment a 1 cifra

6 display a sette segmenti (6 cifre) a catodo comune.

Il problema degli I/O 0 e 1 è che sono condivisi con l'interfaccia seriale, perciò togli Serial.begin(9600);
Se non scrivi nulla sulla seriale, però, non dovrebbe dare problemi...

Grazie a tutti, ecco la versione modificata e corretta come da indicazioni (principalmente da Datman) che funziona perfettamente.

// Example sketch for interfacing with the DS1302 timekeeping chip.
#include <stdio.h>
#include <DS1302.h>


long num = 0; // vaore di 6 cifre da scomporre
long num1 ;
long num2 ;
long num3 ;
long num4 ;
long num5 ;
long num6 ;


long v_sec;
long v_min;
long v_hr;


byte values[] = {
  //hgfedcba
  B10111111, // 0  -0
  B10000110, // 1  -1
  B11011011, // 2  -2
  B11001111, // 3  -3
  B11100110, // 4  -4
  B11101101, // 5  -5
  B11111101, // 6  -6
  B10000111, // 7  -7
  B11111111, // 8  -8
  B11101111, // 9  -9
};


byte values2[] = {
  B00011111, // PIN 13
  B00101111, // PIN 12
  B00110111, // PIN 11
  B00111011, // PIN 10
  B00111101, // PIN 9
  B00111110, // PIN 8
};


namespace {


const int kCePin   = A0;  // Chip Enable
const int kIoPin   = A1;  // Input/Output
const int kSclkPin = A2;  // Serial Clock


// Create a DS1302 object.
DS1302 rtc(kCePin, kIoPin, kSclkPin);


void printTime() {
  // Get the current time and date from the chip.
  Time t = rtc.time();
  v_hr = t.hr;
  v_min = t.min;
  v_sec = t.sec;


  num = ((v_hr * 10000) + (v_min * 100) + v_sec);
}


}  // namespace


void setup() {
  //  Serial.begin(9600);
  //  Serial.println("Prove_clock/prova_05");


  DDRD = B11111111;
  DDRB = B11111111;


  //rtc.writeProtect(false);
  //rtc.halt(false);


  //Time t(2020, 10, 3, 17, 38, 00, Time::kSaturday);


  //rtc.time(t);
}


void loop() {
  printTime();
  numero();


  PORTB = values2[0];
  PORTD = values[num1];
  delay (3);


  PORTB = values2[1];
  PORTD = values[num2];
  delay (3);


  PORTB = values2[2];
  PORTD = values[num3];
  delay (3);


  PORTB = values2[3];
  PORTD = values[num4];
  delay (3);


  PORTB = values2[4];
  PORTD = values[num5];
  delay (3);


  PORTB = values2[5];
  PORTD = values[num6];
  delay (3);
}


void numero() {
  num6 = (num / 100000);
  num5 = ((num - (num6 * 100000)) / 10000);
  num4 = ((num - (num6 * 100000) - (num5 * 10000)) / 1000);
  num3 = ((num - (num6 * 100000) - (num5 * 10000) - (num4 * 1000)) / 100);
  num2 = ((num - (num6 * 100000) - (num5 * 10000) - (num4 * 1000) - (num3 * 100)) / 10);
  num1 = ((num - (num6 * 100000) - (num5 * 10000) - (num4 * 1000) - (num3 * 100) - (num2 * 10)));


}

Vedo, comunque, che hai complicato un po' l'estrazione delle cifre: a che serve comporre num? Basta estrarre num1 e num2 dalle ore, num3 e num4 dai minuti e num5 e num6 dai secondi.

Vero, ma in questo modo visualizzo anche lo 0 per le ore inferiori alle 10.

Saluti
Enrico

Certo, sarebbe più leggibile se values2 si chiamasse display e se values si chiamasse numero :slight_smile:

[color=#222222]// Example sketch for interfacing with the DS1302 timekeeping chip.[/color]
[color=#222222]#include <stdio.h>[/color]
[color=#222222]#include <DS1302.h>[/color]

[color=#222222]long num = 0; // vaore di 6 cifre da scomporre[/color]
[color=#222222]long num1 ;[/color]
[color=#222222]long num2 ;[/color]
[color=#222222]long num3 ;[/color]
[color=#222222]long num4 ;[/color]
[color=#222222]long num5 ;[/color]
[color=#222222]long num6 ;[/color]

[color=#222222]long v_sec;[/color]
[color=#222222]long v_min;[/color]
[color=#222222]long v_hr;[/color]

[color=#222222]byte numero[] = {[/color]
[color=#222222] //hgfedcba[/color]
[color=#222222] B10111111, // 0  -0[/color]
[color=#222222] B10000110, // 1  -1[/color]
[color=#222222] B11011011, // 2  -2[/color]
[color=#222222] B11001111, // 3  -3[/color]
[color=#222222] B11100110, // 4  -4[/color]
[color=#222222] B11101101, // 5  -5[/color]
[color=#222222] B11111101, // 6  -6[/color]
[color=#222222] B10000111, // 7  -7[/color]
[color=#222222] B11111111, // 8  -8[/color]
[color=#222222] B11101111, // 9  -9[/color]
[color=#222222]};[/color]

[color=#222222]byte display[] = {[/color]
[color=#222222] B00011111, // PIN 13[/color]
[color=#222222] B00101111, // PIN 12[/color]
[color=#222222] B00110111, // PIN 11[/color]
[color=#222222] B00111011, // PIN 10[/color]
[color=#222222] B00111101, // PIN 9[/color]
[color=#222222] B00111110, // PIN 8[/color]
[color=#222222]};[/color]

[color=#222222]namespace {[/color]
[color=#222222]const int kCePin   = A0;  // Chip Enable[/color]
[color=#222222]const int kIoPin   = A1;  // Input/Output[/color]
[color=#222222]const int kSclkPin = A2;  // Serial Clock[/color]

[color=#222222]// Create a DS1302 object.[/color]
[color=#222222]DS1302 rtc(kCePin, kIoPin, kSclkPin);[/color]

[color=#222222]void printTime()[/color]
[color=#222222] {[/color]
[color=#222222] // Get the current time and date from the chip.[/color]
[color=#222222] Time t = rtc.time();[/color]
[color=#222222] v_hr = t.hr;[/color]
[color=#222222] v_min = t.min;[/color]
[color=#222222] v_sec = t.sec;[/color]
[color=#222222] num = ((v_hr * 10000) + (v_min * 100) + v_sec);[/color]
[color=#222222] }[/color]
[color=#222222]}  // namespace[/color]


[color=#222222]void setup()[/color]
[color=#222222]{[/color]
[color=#222222] //  Serial.begin(9600);[/color]
[color=#222222] //  Serial.println("Prove_clock/prova_05");[/color]

[color=#222222] DDRD = B11111111;[/color]
[color=#222222] DDRB = B11111111;[/color]

[color=#222222] //rtc.writeProtect(false);[/color]
[color=#222222] //rtc.halt(false);[/color]
[color=#222222] //Time t(2020, 10, 3, 17, 38, 00, Time::kSaturday);[/color]
[color=#222222] //rtc.time(t);[/color]
[color=#222222]}[/color]

[color=#222222]void loop()[/color]
[color=#222222] {[/color]
[color=#222222] printTime();[/color]
[color=#222222] valore();[/color]

[color=#222222] PORTB = values2[0];[/color]
[color=#222222] PORTD = values[num1];[/color]
[color=#222222] delay (3);[/color]

[color=#222222] PORTB = values2[1];[/color]
[color=#222222] PORTD = values[num2];[/color]
[color=#222222] delay (3);[/color]

[color=#222222] PORTB = values2[2];[/color]
[color=#222222] PORTD = values[num3];[/color]
[color=#222222] delay (3);[/color]

[color=#222222] PORTB = values2[3];[/color]
[color=#222222] PORTD = values[num4];[/color]
[color=#222222] delay (3);[/color]

[color=#222222] PORTB = values2[4];[/color]
[color=#222222] PORTD = values[num5];[/color]
[color=#222222] delay (3);[/color]

[color=#222222] PORTB = values2[5];[/color]
[color=#222222] PORTD = values[num6];[/color]
[color=#222222] delay (3);[/color]
[color=#222222]}[/color]


[color=#222222]void valore()[/color]
[color=#222222]{[/color]
[color=#222222] num6 = (num / 100000);[/color]
[color=#222222] num5 = ((num - (num6 * 100000)) / 10000);[/color]
[color=#222222] num4 = ((num - (num6 * 100000) - (num5 * 10000)) / 1000);[/color]
[color=#222222] num3 = ((num - (num6 * 100000) - (num5 * 10000) - (num4 * 1000)) / 100);[/color]
[color=#222222] num2 = ((num - (num6 * 100000) - (num5 * 10000) - (num4 * 1000) - (num3 * 100)) / 10);[/color]
[color=#222222] num1 = ((num - (num6 * 100000) - (num5 * 10000) - (num4 * 1000) - (num3 * 100) - (num2 * 10)));[/color]
[color=#222222]}[/color]

Nooo! Ho selezionato tutto e ci ha messo color!!! >:(
Rinuncio.

Incuriosito, sono andato a informarmi su namespace: mi sembra che qui non ci sia ragione di usarlo...

OK, raccolto i suggerimenti, .......ma, complichiamoci ulteriormente la vita ed aggiungiamo la data.

// Example sketch for interfacing with the DS1302 timekeeping chip.
#include <stdio.h>
#include <DS1302.h>


long num = 0; // valore di 6 cifre da scomporre
long num1 ;
long num2 ;
long num3 ;
long num4 ;
long num5 ;
long num6 ;


long v_sec;
long v_min;
long v_hr;
long v_day;
long v_mon;
long v_year;


int cambio = 17;


byte numero[] = {
  //hgfedcba
  B10111111, // 0  -0
  B10000110, // 1  -1
  B11011011, // 2  -2
  B11001111, // 3  -3
  B11100110, // 4  -4
  B11101101, // 5  -5
  B11111101, // 6  -6
  B10000111, // 7  -7
  B11111111, // 8  -8
  B11101111, // 9  -9
};


byte display[] = {
  B00011111, // PIN 13
  B00101111, // PIN 12
  B00110111, // PIN 11
  B00111011, // PIN 10
  B00111101, // PIN 9
  B00111110, // PIN 8
};


namespace {


const int kCePin   = A0;  // Chip Enable
const int kIoPin   = A1;  // Input/Output
const int kSclkPin = A2;  // Serial Clock


// Create a DS1302 object.
DS1302 rtc(kCePin, kIoPin, kSclkPin);


void printTime() {
  // Get the current time and date from the chip.
  Time t = rtc.time();
  v_hr = t.hr;
  v_min = t.min;
  v_sec = t.sec;


  num = ((v_hr * 10000) + (v_min * 100) + v_sec);
}


void printDate() {
  Time t = rtc.time();
  v_day = t.date;
  v_mon = t.mon;
  int t_year =  (t.yr / 100);
  v_year = (t.yr - (t_year * 100));


  num = ((v_day * 10000) + (v_mon * 100) + v_year);
}


}  // namespace


void setup() {
  //  Serial.begin(9600);
  //  Serial.println("Prove_clock/prova_05");


  DDRD = B11111111;
  DDRB = B11111111;


  //rtc.writeProtect(false);
  //rtc.halt(false);


  //Time t(2020, 10, 3, 17, 38, 00, Time::kSaturday);


  //rtc.time(t);


  pinMode(cambio, INPUT_PULLUP);
}


void loop() {
  if (digitalRead(cambio) == LOW)  {
    printDate();
  } else {
    printTime();
  }


  valore();


  PORTB = display[0];
  PORTD = numero[num1];
  delay (3);


  PORTB = display[1];
  PORTD = numero[num2];
  delay (3);


  PORTB = display[2];
  PORTD = numero[num3];
  delay (3);


  PORTB = display[3];
  PORTD = numero[num4];
  delay (3);


  PORTB = display[4];
  PORTD = numero[num5];
  delay (3);


  PORTB = display[5];
  PORTD = numero[num6];
  delay (3);
}


void valore() {
  num6 = (num / 100000);
  num5 = ((num - (num6 * 100000)) / 10000);
  num4 = ((num - (num6 * 100000) - (num5 * 10000)) / 1000);
  num3 = ((num - (num6 * 100000) - (num5 * 10000) - (num4 * 1000)) / 100);
  num2 = ((num - (num6 * 100000) - (num5 * 10000) - (num4 * 1000) - (num3 * 100)) / 10);
  num1 = ((num - (num6 * 100000) - (num5 * 10000) - (num4 * 1000) - (num3 * 100) - (num2 * 10)));


}

Saluti