[OT ITA] Lo spamm bar (Part 1)

Guglielmo

Io questo me lo ricordo ma non avevo la trifase, probabilmente esisteva anche per la monofase.
Forse ne ho uno da qualche parte nella sua scatola!

zoomx:
Io questo me lo ricordo ma non avevo la trifase, probabilmente esisteva anche per la monofase.

Certamente, anche io ai bei tempi avevo questo:


Guglielmo

Si! E' lui! Il 1631!

gpb01: Se vuoi andare su cose pi√Ļ spinte, allora prendi la "Curiosity HPC", QUESTA,, prendi a parte un PIC18LF46K42 e ... vedrai che potrai fare belle cose ;)

Ho fatto un sopralluogo, interessante, per ora studio e poi nel caso compro. Devo fare sempre i conti con la mia smisurata curiosità e la mia incapacità di starci effettivamente dietro ;)

Maurotec: A quanto detto da Guglielmo ci aggiungo un link su (CIP)

Grazie, essendo a zero su queste cose, un po' di roba da studiare me la piglio con piacere. In alcuni casi ho già sentito l'esigenza, ma per ora ho cercato di risolvere con buffer giocando sul momento in cui dedicare il micro a certi compiti. Tipicamente sulle comunicazioni che impegnano per lunghi periodi e sono difficilmente spezzettabili. Su altre cose basta rateizzare i compiti ;)

Maurotec: Le logiche programmabili dalla loro hanno il vantaggio di potere eseguire dei processi in parallelo sincronizzandoli, ma parliamo di un altro mondo, altro modo di ragionare sempre ché si voglia realizzare un processo che ancora non è stato sintetizzato da altri.

Indubbiamente alla fine si pu√≤ fare mooolto di pi√Ļ rispetto a quello per cui mi sono state "consigliate". Il caso da cui era partito tutto era un semaforo quadruplo che avevo gestito, sulla carta, con due soli pin di Arduino e alcune porte AND e NOT per calcolare le accensioni in mutua esclusione alternate. Di fatto usavo un pin per rosso e verde e uno per giallo. Per tutti e 4 i semafori a incrocio ad x, quindi pilotati uguali a 2 a 2 e opposti tra le coppie. Quindi dovevano "risolvermi" il problema dei cip con le varie porte logiche, e quindi sarebbe stato un uso un po' becero rispetto alle effettive potenzialit√† :P

Maurotec: Un esempio che con logiche programmabili e sicuramente con MCU con CIP sarebbe venuto meglio è il seguente brevemente descritto: ...

Interessante come esempio, per passare un pelo oltre alla mera replica di porte logiche elementari. Ovviamente qui si deve ragionare in logica booleana calandola poi nella pratica tenendo sotto controllo i ritardi di propagazione e la sincronizzazione. Quindi non ragioni pi√Ļ in ternime di istruzioni ma di cicli di clock e fronti di salita/discesa e ritardi. Una cosa che mi √® sempre piaciuta ma che richiede un sacco di tempo per starci dietro.

Mi sono fatto una prima idea, grazie ad entrambi e k+. Mi avete fatto da bussola ;)

Ovviamente qui si deve ragionare in logica booleana calandola poi nella pratica tenendo sotto controllo i ritardi di propagazione e la sincronizzazione. Quindi non ragioni pi√Ļ in ternime di istruzioni ma di cicli di clock e fronti di salita/discesa e ritardi. Una cosa che mi √® sempre piaciuta ma che richiede un sacco di tempo per starci dietro.

Per certi tipi di applicazione indipendentemente dal dispositivo che vuoi programmare sei costretto a rispettare dei vincoli temporali per potere dire che l'applicazione non fallisce, alle volte basta usare una MCU pi√Ļ prestante, in altri casi e per altri motivi una MCU non √® la soluzione adatta e non rimane altro che le logiche programmabili di cui alcuni chip mischiano CPU e logiche assieme.

PS: Esiste anche VHDL Analog di cui so che viene usato per creare dei modelli compatibili con alcuni simulatori ad esempio Qucs.

vhdl analog

Devo fare sempre i conti con la mia smisurata curiosità e la mia incapacità di starci effettivamente dietro ;)

Come ti capisco, per questo alle volte ho una infarinatura di questo e di quello che è meglio di niente e preferisco tornare ad approfondire gli AVR ed in genere le MCU. Poi per come sono fatto io che dopo sei mesi senza programmare rileggo miei programmi e mi meraviglio di ciò che ho scritto e fatico pure a capire e mi chiedo ma come ci sono arrivato. Quindi avrò un garbage collector nel mio cervello che non riesco a controllare. :D

Ciao.

Io sento "odore" di PSoC. Solo che poi ti ritrovi la casa piena di sistemi di sviluppo! :D :grinning:

Maurotec: Come ti capisco, per questo alle volte ho una infarinatura di questo e di quello che è meglio di niente e preferisco tornare ad approfondire gli AVR ed in genere le MCU. Poi per come sono fatto io che dopo sei mesi senza programmare rileggo miei programmi e mi meraviglio di ciò che ho scritto e fatico pure a capire e mi chiedo ma come ci sono arrivato. Quindi avrò un garbage collector nel mio cervello che non riesco a controllare. :D

Sei la mia fotocopia ;) A me piace infarinarmi su tutto, ma poi si aprono mondi sterminati se vuoi fare il passo successivo, quindi anche io per il momento resto sull'ATmega della UNO, quindi addirittura un sottoinsieme degli AVR, ma intanto spingo la mente oltre. Per quanto riguarda il rileggere il proprio codice dopo mesi e non capirlo, io risolvo scrivendo pi√Ļ commenti che codice :P La mia memoria a breve termine √® moooolto a breve termine, nella sala della memoria a lungo termine, invece, c'√® l'eco ;)

maubarzi: Per quanto riguarda il rileggere il proprio codice dopo mesi e non capirlo, io risolvo scrivendo pi√Ļ commenti che codice

... posso suggerire a tutti l'utilizzo di "doxygen"?

E' il prodotto pi√Ļ usato ed √® ormai uno standard di fatto. Se ben utilizzato, alla fine, vi genera pure il reference manual della vostra applicazione ;)

Guglielmo

P.S.: Ad esempio tutti i codici generati da MCC (MPLAB Code Configurator) sono proprio commentati con l'utilizzo di "doxygen" :)

maubarzi: Sei la mia fotocopia ;)

Per quanto riguarda il rileggere il proprio codice dopo mesi e non capirlo, io risolvo scrivendo pi√Ļ commenti che codice :P

All'ora ci hanno fatti con lo stampino, dato che le vostre descrizioni si possono applicare anche a me, intendo a parte la mia superiore bellezza...

per quanto riguarda il commentare il codice, ricordo di aver letto qui sul forum, forse prima di iscrivermi quando era ancora un arduinista anonimo bustocco, che il buon programmatore in 'C' mette pi√Ļ righe vuote che righe scritte

Standardoil: All'ora ci hanno fatti con lo stampino ... a parte la mia superiore bellezza

Fortunello ad essere stato stampato per primo a stampo ancora liscio e pulito ;)

Fortuni si nasce e modestamente.... io nacqui....

Io sapevo: c'è chi può e chi non può... io può!

E‚Äô il prodotto pi√Ļ usato ed √® ormai uno standard di fatto. Se ben utilizzato, alla fine, vi genera pure il reference manual della vostra applicazione :wink:

Ma volendo ci puoi anche scrivere un libro o un AN come nell’immagine allegata, il bello che come output oltre ad html hai anche tex/latex.

per quanto riguarda il commentare il codice, ricordo di aver letto qui sul forum, forse prima di iscrivermi quando era ancora un arduinista anonimo bustocco, che il buon programmatore in ‚ÄėC‚Äô mette pi√Ļ righe vuote che righe scritte

Certamente aiuta a comprendere cosa fa quella funzione, ma di certo non puoi commentare anche il come e quando il come era già intrigato al tempo in cui lo hai scritto ora che lo leggi a distanza di tempo ti pare ostrogoto, un esempio guarda lo leggiamo assieme per la prima volta.

#ifndef DATAWRAPPER_H
#define DATAWRAPPER_H

#include "gtype.h"

/**
 *  \file
 *  \brief  data types and functions to parameter
 *
 *  It's contains data type to wrap real variable used as parameters
 **/


typedef enum {
      Uint8     =   0x00        /*!< Imposta il tipo uint8_t    */
    , Uint16    =   0x01        /*!< Imposta il tipo uint16_t   */
    , Int8      =   0x02        /*!< Imposta il tipo int8_t     */
    , Int16     =   0x03        /*!< Imposta il tipo int16_t    */
    , AsFloat   =   0x04        /*!< Lo mostra come float (float)(value / 100)  */
    , ToFlash   =   0x08        /*!< La variabile si trova in flash */
    , ReadOnly  =   0x10        /*!< Il valore non può essere modificato    */
    , NoShowIfZero  =   0x20    /*!< Se il valore è zero (0) salta al prossimo paramentro */

} eType;

/**
 *  \brief This is the container to parameter value
 *
 *  It contains pointer ptrToData to real variable of type described by flags
 **/
typedef struct
{
    bb_flags            flags;          /*!<    define type of void_ptr     */
    void_ptr            ptrToData;      /*!<    Void pointer to origin variable     */

} DataWrapper;

typedef int16_t UniData;

void toUniData(const DataWrapper *restrict wrap, UniData * restrict ud);

#endif // DATAWRAPPER_H

Questo √® comprensibile, ma quello che segue contiene dei commenti scritti allora in cui giudicavo io codice ‚Äėcriptico‚Äô

#include "parameter.h"
#include "parameter_p.h"
#include <avr/pgmspace.h>
#include "utils.h"

UniData data;
UniData dataMin;
UniData dataMax;
// ie. SIZEOF(3) result 2 byte
#define SIZEOF(value)   ((value & _BV(0)) + 1)

// bufferDataMin and bufferDataMax are ram container to fixed value writed in flash
static uint8_t bufferDataMin[2];
static uint8_t bufferDataMax[2];

void parameterRead(const ItemMenu *im, ParameterRaw *restrict p)
{
    Parameter_p par_p;
    uint8_t bufferIndex = 0;

    // Read Parameter_p from flash at address saved in ItemMenu.parameter and save it par_p
    memcpy_P(&par_p, im->parameter, sizeof(Parameter_p));
    // set name to raw flash address
    p->name = par_p.name;

    // read DataWrapper from flash at address saved in Parameter_p.data and save it in ParameterRaw.data
    memcpy_P(&p->data, par_p.data, sizeof(DataWrapper));
    // read DataWrapper from flash at address saved in Parameter_p.dataMin and save it in ParameterRaw.dataMin
    memcpy_P(&p->dataMin, par_p.dataMin, sizeof(DataWrapper));
    // read DataWrapper from flash at address saved in Parameter_p.dataMax and save it in ParameterRaw.dataMax
    memcpy_P(&p->dataMax, par_p.dataMax, sizeof(DataWrapper));

    // data è sempre in ram, in seguito potrebbe essere necessario mostrare un dato in sola lettura
    // presente in flash, come ad esempio firmware version (FiU) o eeprom protocol version (EPU)

    // if ptrToData point to flash copy data in buffer and update ptrToData a new address in ram
    if (p->dataMin.flags & ToFlash) {
        // very encrypted code
        bufferIndex = (~p->dataMin.flags & _BV(0));
        memcpy_P(&bufferDataMin[bufferIndex], p->dataMin.ptrToData, SIZEOF(p->dataMin.flags));
        p->dataMin.ptrToData = (void*)&bufferDataMin[bufferIndex];

    }
    // if ptrToData point to flash copy data in buffer and update ptrToData a new address in ram
    if (p->dataMax.flags & ToFlash) {
        // very encrypted code
        bufferIndex = (~p->dataMax.flags & _BV(0));
        memcpy_P(&bufferDataMax[(~p->dataMax.flags & _BV(0))], p->dataMax.ptrToData, SIZEOF(p->dataMax.flags));
        p->dataMax.ptrToData = (void*)&bufferDataMax[bufferIndex];

    }
}

Bene i commenti aiutano a capire cosa fa, ma come ci sono arrivato?
Quei commenti ‚Äú// very encrypted code‚ÄĚ lasciano intendere che anche allora lo consideravo difficile da leggere
e da scrivere.

Il fatto è che ci si inventa dei meccanismi complessi senza rendersene conto perché seguiamo lo sviluppo
agile e arriviamo a mettere su dei contenitori di parametri generici di cui alcuni sono riservati (pertanto ci serve un flag)
ma se hai la password puoi accedere e modificare il valore a meno che non sia fisso (e ci serve un’altra flag)
Il tutto per risparmiare memoria Eeprom per centinaia di parametri modificabili dall’utente pigiando i tasti giusti.

Poi ci accorgiamo che per ‚Äúsemplificare‚ÄĚ sia int8 uint8 int16, che float che altro siano visti dall‚Äôapplicazione come UniData e quindi ci servono tanti altri flag e tanto altro che al momento in cui lo scrivi lo hai in testa chiaro e pi√Ļ vai avanti pi√Ļ si chiariscono le ide. Sai gi√† che un float in Eeprom ti costa 4 byte e lo conservi come interno ma per stamparlo sul display
l’utente vuole un float serve un flag di modo che convertiamo solo per stamparlo.

Poi stai lontano dalla programmazione per 6 mesi e la faccia che fai quando leggi il code che sai di avere scritto tu e
pi√Ļ o meno :fearful:

Ciao.

Maurotec:
Certamente aiuta a comprendere cosa fa quella funzione, ma di certo non puoi commentare anche il come e quando il come era già intrigato al tempo in cui lo hai scritto ora che lo leggi a distanza di tempo ti pare ostrogoto, un esempio guarda lo leggiamo assieme per la prima volta.

che rileggere il tuo stesso codic dopo 6 mesi / 1 anno faccia scoprire abissi di smemoratezza, sono d’accordo con te
ma secondo me hai due cose da fare: uno √® ‚Äúdescrivere‚ÄĚ cosa fa la funzione, e questo √® pacifico, √® il minimo e secondo me va fatto all‚Äôinizio della funzione, oltre che tenerne traccia in altra parte (manuale, note di utilizzo, altro, io non programmo per lavoro, mi basta un file .txt associato all‚Äôaccrocchio)
secondo √® proprio ‚Äúcommentare‚ÄĚ COME lavora il tuo codice, e questo √® opzionale, dato che per definizione SE lavora bene lo prendi per oro colato e lo tratti come se fosse una libreria pre-compilata: la usi e non la guardi
se decidi di commentare COME lavora una funzione o una parte di codice lo fai ‚Äúbene‚ÄĚ
cose del tipo:

uint8_b prova=0; // prova è di tipo byte

sono inutili, lo leggo anche tra 6 anni che prova è un byte, ma non saprò a cosa serve

byte i // contatore del byte in trattamento, occhio che stringhe devono essere <255

qui so che tratterò una stringa, come si chiama l’indice e ho anche subito indicazione di una criticità
leggo molti commenti del primo tipo, pochi del secondo
[/code]

Io descrivo il principio dell'algoritmo in testa a tutto e poi metto in evidenza le cose particolari che indicano della cose gestite in modo particolare o come eccezione che magari a distanza di tempo se non te ne ricordi rischi che ti portino a fare modifiche catastrofiche. Ad es. che un array zero based lo uso come uno based perch√® lo zero me lo riservo per una cosa particolare. Oppure che non faccio un test apposito perch√® quella condizione deve essere garantita dal chiamante e se arriva qui non verificata √® ormai troppo tardi, quindi √® giusto che si pianti col botto. Ebbene si, io sono per rispettare una delle leggi dell'open source: se c'√® un errore si deve manifestare nel modo pi√Ļ catastrofico possibile che non significa sputtanamento dei dati ma magari piantamento del programma. Perch√® questo? Perch√® cos√¨ al primo caso lo correggi, altrimenti nascondi il problema che si ripercuote sui dati e quando lo correggi ormai ha creato casini in ogni dove, invece l'errore dovrebbe essere rilevato immediatamente e corretto. Ovvio che poi l'applicazione effettiva di questo principio va fatta con testa, per√≤ la tendenza mia √® questa. O precisione o morte!

Guglielmo

maubarzi: ... Oppure che non faccio un test apposito perchè quella condizione deve essere garantita dal chiamante e se arriva qui non verificata è ormai troppo tardi, quindi è giusto che si pianti col botto. ...

Ma usare la macro assert() no ? ? ? ;)

Dai un'occhiata QUI a come "personalizzarla" per usare le Serial.println() per i messaggi di errore :)

Guglielmo

Io uso il C solo con Arduino, mi riferivo all'ambito lavorativo ;)

A scanso di equivoci, quando dico:

maubarzi: ...quindi è giusto che si pianti col botto.

Non intendo il crash del sistema ma l'interruzione della transazione con "rollback" di ogni modifica parziale e incoerente o il raggiungimento di uno stato stabile e sicuro nel caso di attuatori. Cioè piuttosto di elaborare dati/azioni incoerenti/casuali non elaboro nulla e mi riporto in una situazione coerente. E questo per gli errori veramente imprevisti, quelli previsti avranno la relativa gestione dell'eccezione e azioni specifiche, ecc. ecc. ecc.

cambiando discorso... ma c'è epidemia di GSM? vuoi vedere che il compito di scuola non erano le fresatrici come credevo pochi mesi fa?