Pic Micro, Arduino, Atmel, Microchip, Freescale, Texas Instrument, ecc. Strumenti di sviluppo, firmware e progetti.
Avatar utente
da GioRock
#4980
Essendo a conoscenza che molti utenti alle prime armi con i PIC o microcontrollori che dir si voglia, tendono a sviluppare applicazioni prendendo spunto dagli innumerevoli esempi postati in rete, nella fattispecie e facendo una statistica sulle richieste di aiuto lette, queste puntano essenzialmente allo sviluppo di Orologi o Timer in generale.

Dalla Nixie ai Display a LED passando per i più moderni LCD, bene o male questi programmi fanno più o meno le stesse cose, data, ore e temperatura sono quelle maggiormente utilizzate, c'è chi utilizza moduli RTC per avere meno problemi nella stesura del codice o chi li abbelisce con funzioni personalizzate quali l'aggiunta della data di compleanno o addirittura il segno Zodiacale scandito mese per mese etc...

Una cosa però non ho mai visto scritta in questi codici, ovvero la corretta segnalazione della ricorrenza Pasquale che, come tutti sappiamo non occore sempre nello stesso giorno, quindi ho scritto una piccola funzione che molti di Voi magari troveranno utile per abbellire le varie creazioni:


MIKROBASIC CODE:

Codice: Seleziona tutto'-----------------------------------------------------------------
 PROGRAM EasterDayCalc ' MikroBasic
'-----------------------------------------------------------------

SUB FUNCTION EasterDay(DIM Year AS WORD) AS WORD
DIM m AS WORD
DIM n AS WORD
DIM Y AS WORD
DIM a AS WORD
DIM b AS WORD
DIM c AS WORD
DIM d AS WORD
DIM e AS WORD
DIM ED AS WORD

    Y = Year
   
    m = 24
    n = 5
   
    a = Y MOD 19
    b = Y MOD 4
    c = Y MOD 7
    d = (19 * a + m) MOD 30
    e = (2 * b + 4 * c + 6 * d + n) MOD 7
   
    ED = 22 + d + e
   
    IF ED <= 31 THEN
        ED = ED * $100 + 3 ' Marzo
    ELSE
        ED = (d + e - 9) * $100 + 4 ' Aprile
    END IF
   
    result = ED ' ritorna il giorno insieme al mese
                ' sotto forma di una WORD (max. 7'940)
                ' 31 * $100 + 4 - 2 BYTE GIORNO + 2 BYTE MESE
                ' MSB |G|G|M|M| LSB

END SUB

'-----------------------------------------------------------------

main:
DIM Pasqua AS WORD
DIM GiornoDiPasqua AS BYTE
DIM MeseDiPasqua AS BYTE

    Pasqua = EasterDay(2017)
    GiornoDiPasqua = byte((Pasqua / $100) MOD $100)
    MeseDiPasqua = byte(Pasqua MOD $100)

END.



MIKROC CODE:

Codice: Seleziona tutto//-----------------------------------------------------------------
// PROGRAM EasterDayCalc - MikroC
//-----------------------------------------------------------------

unsigned EasterDay(unsigned Year) {
unsigned m;
unsigned n;
unsigned Y;
unsigned a;
unsigned b;
unsigned c;
unsigned d;
unsigned e;
unsigned ED;

    Y = Year;
   
    m = 24;
    n = 5;
   
    a = Y % 19;
    b = Y % 4;
    c = Y % 7;
    d = (19 * a + m) % 30;
    e = (2 * b + 4 * c + 6 * d + n) % 7;
   
    ED = 22 + d + e;
   
    if (ED <= 31) {
        ED = ED * 0x100 + 3; // Marzo
    } else {
        ED = (d + e - 9) * 0x100 + 4; // Aprile
    }
   
    return ED; // ritorna il giorno insieme al mese
               // sotto forma di una UNSIGNED (max. 7'940)
               // 31 * 0x100 + 4 - 2 BYTE GIORNO + 2 BYTE MESE
               // MSB |G|G|M|M| LSB

}

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

void main() {
unsigned Pasqua;
unsigned short GiornoDiPasqua;
unsigned short MeseDiPasqua;

    Pasqua = EasterDay(2017);
    GiornoDiPasqua = (unsigned short)((Pasqua / 0x100) % 0x100);
    MeseDiPasqua = (unsigned short)(Pasqua % 0x100);


}




Altra cosa, è il calcolo dell'anno bisestile che è abbastanza semplice, si fà il modulo di 4 dell'anno e "se il risultato non da resto, allora l'anno è bisesto": :mrgreen:

MIKROBASIC CODE:

Codice: Seleziona tutto
    BYTE LeapYear = byte((YEAR MOD 4) = 0)



MIKROC CODE:

Codice: Seleziona tutto
    unsigned short LeapYear = (unsigned short)((YEAR % 4) == 0);

Bios, double ringraziano
da zioelp
#4981
GioRock ha scritto:Altra cosa, è il calcolo dell'anno bisestile che è abbastanza semplice, si fà il modulo di 4 dell'anno e "se il risultato non da resto, allora l'anno è bisesto": :mrgreen:

Per molti anni bisestili è sufficiente accertare la divisibilità per 4, ma per alcuni è necessario svolgere uno o due calcoli in più.
Il 1900, ad esempio, è divisibile per 4 ma non è stato bisestile.
In rete ci sono tulle le indicazioni per il calcolo completo, ma in due righe l'algoritmo si può sintetizzare così:
Se l'anno è divisibile per 4 e NON è divisibile per 100, allora è bisestile.
Se l'anno è divisibile per 4 ed è divisibile per 100 ed è divisibile per 400, allora è bisestile.
Buona Pasqua :)
#4982
Hai ragione Zio, ero andato troppo a memoria ed ho tralasciato i particolari, le nuove funzioni sono:

MIKROBASIC CODE:

Codice: Seleziona tuttoSUB FUNCTION IsLeapYear(DIM Year AS WORD) AS BYTE
    IF (Year MOD 4) = 0 THEN
        result = byte(((Year MOD 100) > 0) OR ((Year MOD 400) = 0))
    END IF
END SUB



MIKROC CODE:

Codice: Seleziona tuttounsigned short IsLeapYear(unsigned Year) {
    if ((Year % 4) == 0) {
        return (unsigned short)(((Year % 100) > 0) || ((Year % 400) == 0));
    }
}

Bios ringraziano
Avatar utente
da double
#4989
Bel lavoro GioRock, Gauss ne sarebbe felice!

Tuttavia (c'è sempre un tuttavia) quella è la pasqua cattolica e di pasque ce ne sono tre: quella cattolica e riformata, quella ortodossa e quella ebraica. Tutte si basano sulla luna piena di primavera ma secondo tre calendari diversi: il nuovo gregoriano solare, il vecchio giuliano solare e l'antico ebraico lunare di 13 mesi. Ogni tanto due pasque coincidono e raramente anche tutte e tre, i soliti capricci della luna.

Temo di aver risvegliato un demone.....
Avatar utente
da GioRock
#4993
OK, per la questione GIULIANO e GREGORIANO ho risolto abbastanza facilmente, per la Pasqua Ebraica ci devo lavorare sopra, quindi aspetterò che ci sia qualche richiesta... 8-)

MIKROBASIC CODE:

Codice: Seleziona tutto'-----------------------------------------------------------------
 PROGRAM EasterDayCalc ' MikroBasic
'-----------------------------------------------------------------

CONST GREGORIAN AS BYTE = 0
CONST JULIAN AS BYTE = 1

SUB FUNCTION EasterDay(DIM Year AS WORD, CT AS BYTE) AS WORD
DIM m AS WORD
DIM n AS WORD
DIM Y AS WORD
DIM a AS WORD
DIM b AS WORD
DIM c AS WORD
DIM d AS WORD
DIM e AS WORD
DIM ED AS WORD

    Y = Year

    IF CT = GREGORIAN THEN
        m = 24
        n = 5
    ELSE
        m = 15
        n = 6
    ENF IF
   
    a = Y MOD 19
    b = Y MOD 4
    c = Y MOD 7
    d = (19 * a + m) MOD 30
    e = (2 * b + 4 * c + 6 * d + n) MOD 7
   
    ED = 22 + d + e
   
    IF ED <= 31 THEN
        ED = ED * $100 + 3 ' Marzo
    ELSE
        ED = (d + e - 9) * $100 + 4 ' Aprile
    END IF
   
    result = ED ' ritorna il giorno insieme al mese
                ' sotto forma di una WORD (max. 7'940)
                ' 31 * $100 + 4 - 2 BYTE GIORNO + 2 BYTE MESE
                ' MSB |G|G|M|M| LSB

END SUB

main:
DIM Pasqua AS WORD
DIM GiornoDiPasqua AS BYTE
DIM MeseDiPasqua AS BYTE

    Pasqua = EasterDay(2017, JULIAN)
    GiornoDiPasqua = byte((Pasqua / $100) MOD $100)
    MeseDiPasqua = byte(Pasqua MOD $100)

END.



MIKROC CODE:

Codice: Seleziona tutto//-----------------------------------------------------------------
// PROGRAM EasterDayCalc - MikroC
//-----------------------------------------------------------------

enum CalendarType {
    GREGORIAN,
    JULIAN
};

unsigned EasterDay(unsigned Year, CalendarType CT) {
unsigned m;
unsigned n;
unsigned Y;
unsigned a;
unsigned b;
unsigned c;
unsigned d;
unsigned e;
unsigned ED;

    Y = Year;
   
    m = (CT == GREGORIAN ? 24 : 15);
    n = (CT == GREGORIAN ? 5 : 6);
   
    a = Y % 19;
    b = Y % 4;
    c = Y % 7;
    d = (19 * a + m) % 30;
    e = (2 * b + 4 * c + 6 * d + n) % 7;
   
    ED = 22 + d + e;
   
    if (ED <= 31) {
        ED = ED * 0x100 + 3; // Marzo
    } else {
        ED = (d + e - 9) * 0x100 + 4; // Aprile
    }
   
    return ED; // ritorna il giorno insieme al mese
               // sotto forma di una UNSIGNED (max. 7'940)
               // 31 * 0x100 + 4 - 2 BYTE GIORNO + 2 BYTE MESE
               // MSB |G|G|M|M| LSB

}

void main() {
unsigned Pasqua;
unsigned short GiornoDiPasqua;
unsigned short MeseDiPasqua;

    Pasqua = EasterDay(2017, GREGORIAN);
    GiornoDiPasqua = (unsigned short)((Pasqua / 0x100) % 0x100);
    MeseDiPasqua = (unsigned short)(Pasqua % 0x100);


}

Avatar utente
da GioRock
#4994
Questi sono i calcoli svolti al Computer per il Secolo corrente con la funzione modificata:

Codice: Seleziona tuttoGREGORIANO     GIULIANO
   
23/04/2000    17/04/2000
15/04/2001    02/04/2001
31/03/2002    22/04/2002
20/04/2003    14/04/2003
11/04/2004    29/03/2004
27/03/2005    18/04/2005
16/04/2006    10/04/2006
08/04/2007    26/03/2007
23/03/2008    14/04/2008
12/04/2009    06/04/2009
04/04/2010    22/03/2010
24/04/2011    11/04/2011
08/04/2012    02/04/2012
31/03/2013    22/04/2013
20/04/2014    07/04/2014
05/04/2015    30/03/2015
27/03/2016    18/04/2016
16/04/2017    03/04/2017
01/04/2018    26/03/2018
21/04/2019    15/04/2019
12/04/2020    06/04/2020
04/04/2021    19/04/2021
17/04/2022    11/04/2022
09/04/2023    03/04/2023
31/03/2024    22/04/2024
20/04/2025    07/04/2025
05/04/2026    30/03/2026
28/03/2027    19/04/2027
16/04/2028    03/04/2028
01/04/2029    26/03/2029
21/04/2030    15/04/2030
13/04/2031    31/03/2031
28/03/2032    19/04/2032
17/04/2033    11/04/2033
09/04/2034    27/03/2034
25/03/2035    16/04/2035
13/04/2036    07/04/2036
05/04/2037    23/03/2037
25/04/2038    12/04/2038
10/04/2039    04/04/2039
01/04/2040    23/04/2040
21/04/2041    08/04/2041
06/04/2042    31/03/2042
29/03/2043    20/04/2043
17/04/2044    11/04/2044
09/04/2045    27/03/2045
25/03/2046    16/04/2046
14/04/2047    08/04/2047
05/04/2048    23/03/2048
25/04/2049    12/04/2049
10/04/2050    04/04/2050
02/04/2051    24/04/2051
21/04/2052    08/04/2052
06/04/2053    31/03/2053
29/03/2054    20/04/2054
18/04/2055    05/04/2055
02/04/2056    27/03/2056
22/04/2057    16/04/2057
14/04/2058    01/04/2058
30/03/2059    21/04/2059
18/04/2060    12/04/2060
10/04/2061    28/03/2061
26/03/2062    17/04/2062
15/04/2063    09/04/2063
06/04/2064    31/03/2064
29/03/2065    13/04/2065
11/04/2066    05/04/2066
03/04/2067    28/03/2067
22/04/2068    16/04/2068
14/04/2069    01/04/2069
30/03/2070    21/04/2070
19/04/2071    06/04/2071
10/04/2072    28/03/2072
26/03/2073    17/04/2073
15/04/2074    09/04/2074
07/04/2075    25/03/2075
26/04/2076    13/04/2076
11/04/2077    05/04/2077
03/04/2078    25/04/2078
23/04/2079    10/04/2079
07/04/2080    01/04/2080
30/03/2081    21/04/2081
19/04/2082    06/04/2082
04/04/2083    29/03/2083
26/03/2084    17/04/2084
15/04/2085    02/04/2085
31/03/2086    25/03/2086
20/04/2087    14/04/2087
11/04/2088    05/04/2088
03/04/2089    18/04/2089
16/04/2090    10/04/2090
08/04/2091    26/03/2091
30/03/2092    14/04/2092
12/04/2093    06/04/2093
04/04/2094    29/03/2094
24/04/2095    11/04/2095
15/04/2096    02/04/2096
31/03/2097    22/04/2097
20/04/2098    14/04/2098
12/04/2099    30/03/2099
27/03/2100    18/04/2100
Avatar utente
da GioRock
#4996
E non solo:

Se la data risultante dalla formula è il 26 aprile, allora la Pasqua cadrà il giorno 19 aprile.

Se la data risultante dalla formula è il 25 aprile e contemporaneamente d = 28, e = 6 e a > 10, allora la Pasqua cadrà il 18 aprile (vedi 2049).

Passo alla correzione cercando di ottimizzare, non voglio avere un overhead esagerato... :sick:
Avatar utente
da double
#4997
ps. ovviamente ho più che apprezzato quel che hai fatto, in particolare il modo con cui fai ritornare DUE valori da una funzione, appaiandone e spaiandone i bites. Userò quel metodo nei miei lavori, l'ho già tradotto in arduinese e (ovviamente) funziona alla grande....
Avatar utente
da GioRock
#4998
Avendo traslato una vecchia funzione in BASIC, non sono stato li a fare troppe correzioni ove possibile...

Quello di cui parli in C lo si può ottimizzare con:

Codice: Seleziona tuttounsigned g = 18;
usigned m = 3;
unsigned x;

    x = (unsigned)(g << 8) | m;  // che è poi uguale a ((g * 256) + 3) ma con meno cicli per il processore



In pratica shiftando a sinistra i bit si moltiplica per due, quindi 2 ^ 8 = 256 che in esadecimale sono 0x100...
Dimmer su aspirazione

Ciao a tutti ho una ventola di aspirazione in came[…]

Visita il nostro canale telegram