- ArduinoQuadro -
- 15/12/2017-
Il progetto di calcolatrice con Arduino, si trasforma in ArduinoQuadro!!
Progetto evoluzione del precedente post "Calcolatrice RPN "
Materiale occorrente:
Arduino UNO
LCD 16x2 I2C
Tastierino a matrice 4x4.
Consultare il precedente post per schema collegamenti, e spiegazioni iniziali.
Rimane invariato lo schema e l'hardware.
_ Costo del materiale molto contenuto.
_ Calcolatrice scientifica di tipo RPN.
Si possono programmare funzioni matematiche e trigonometriche disponibili anche in modo diretto.
E sono disponibili alcune funzionalità di Arduino.
Si potranno realizzare piccoli "sketch" senza dover utilizzare un PC.
Sono disponibili PIN DIGITALI e PIN ANALOGICI che possono essere utilizzati
per input output.
Si potrà scrivere un piccolo programma che potrà essere conservato nella EEPROM.
Una volta lanciata l'esecuzione il programma viene eseguito in modalità "interpetre".
Non si esegue una compilazione quindi l'utilizzo come microcontrollore è limitato,
( sono limitati anche i pin disponibili ( da 0 a 7 sono utilizzati per il tastierino.)
Si potranno visualizzare risultati sul display LCD, immettere dati
dalla tastiera, e/o utilizzare i rimanenti pin disponibili di Arduino, compresi gli analogici.
ArduinoQuadro.
Queste alcune caratteristiche:
Programmazione diretta con la scrittura di piccoli programmi nel linguaggio
"Codice99".
Questo linguaggio appositamente preparato si basa su 99 codici che possono essere
scritti in ram e che successivamente l'interpetre utilizzerà per eseguire la relativa funzione.
Ad ogni codice corrisponde una funzione.
(Alcune funzioni avranno bisogno di più codici)
Ho lasciato disponibili alcuni codici per future versioni.
L'immissione del programma in ram avviene con un micro editor che consente
di scrivere il programma e rivederlo scorrendo le istruzioni ed eventualmente correggere errori.
Una volta scritto il programma potrà essere eseguito e/o salvato nella EEPROM
(salvandolo nella EEPROM rimane permanente fino alla cancellazione).
Questo arduino avrà alcuni registri speciali (catasta operativa)
X, Y, Z, T, U, lastX.
Ci saranno alcuni registri di memoria che i programmi utente potranno utilizzare.
Tastierino a matrice 4x4.
Consultare il precedente post per schema collegamenti, e spiegazioni iniziali.
Rimane invariato lo schema e l'hardware.
_ Costo del materiale molto contenuto.
_ Calcolatrice scientifica di tipo RPN.
Le novità in questo post!!
Ora la calcolatrice è programmabile!
Si possono programmare funzioni matematiche e trigonometriche disponibili anche in modo diretto.
E sono disponibili alcune funzionalità di Arduino.
Si potranno realizzare piccoli "sketch" senza dover utilizzare un PC.
Sono disponibili PIN DIGITALI e PIN ANALOGICI che possono essere utilizzati
per input output.
Si potrà scrivere un piccolo programma che potrà essere conservato nella EEPROM.
Una volta lanciata l'esecuzione il programma viene eseguito in modalità "interpetre".
Non si esegue una compilazione quindi l'utilizzo come microcontrollore è limitato,
( sono limitati anche i pin disponibili ( da 0 a 7 sono utilizzati per il tastierino.)
Si potranno visualizzare risultati sul display LCD, immettere dati
dalla tastiera, e/o utilizzare i rimanenti pin disponibili di Arduino, compresi gli analogici.
ArduinoQuadro.
Queste alcune caratteristiche:
Programmazione diretta con la scrittura di piccoli programmi nel linguaggio
"Codice99".
Questo linguaggio appositamente preparato si basa su 99 codici che possono essere
scritti in ram e che successivamente l'interpetre utilizzerà per eseguire la relativa funzione.
Ad ogni codice corrisponde una funzione.
(Alcune funzioni avranno bisogno di più codici)
Ho lasciato disponibili alcuni codici per future versioni.
L'immissione del programma in ram avviene con un micro editor che consente
di scrivere il programma e rivederlo scorrendo le istruzioni ed eventualmente correggere errori.
Una volta scritto il programma potrà essere eseguito e/o salvato nella EEPROM
(salvandolo nella EEPROM rimane permanente fino alla cancellazione).
Questo arduino avrà alcuni registri speciali (catasta operativa)
X, Y, Z, T, U, lastX.
Ci saranno alcuni registri di memoria che i programmi utente potranno utilizzare.
//******************************************************************************
FUNZIONI PROGAMMABILI E RELATIVI CODICI.
MEMORIE & INDICI = da 00 a 19 (questi codici vengono immessi prima della istruzione che li
utilizza. prima si imposta il numero e poi l'istruzione.
Es. prima 01 poi 67 (STOnn) in questo caso il contenuto di x viene
memorizzato nel regisro mem1
Le istruzioni qui sotto con (*) DEVONO ESSERE PRECEDUTE DALL'INDICE
------------------------------------------------------------------------------------------------------------
I/O = 20 PRINT 21 INPUT da 22 a 29 disp
------------------------------------------------------------------------------------------------------------
ARDUINO = 30 *PINPUT 31 *PIOUT 32 *DWHIGH 33 *DWLOW 34 *DREAD
35 *AREAD 36 *AWRITE 37 *DELAYn 38 *TONE 39 *NOTONE
------------------------------------------------------------------------------------------------------------
CONTROLLO = 40 XmaggioreY? 41 XminoreY? 42 X = Y 43 X maggiore 0? 44 Xminore 0?
45 *INCn 46 END 47 LOOP 48 RTN 49 NOP
-------------------------------------------------------------------------------------------------------FUNZIONI PROGAMMABILI E RELATIVI CODICI.
MEMORIE & INDICI = da 00 a 19 (questi codici vengono immessi prima della istruzione che li
utilizza. prima si imposta il numero e poi l'istruzione.
Es. prima 01 poi 67 (STOnn) in questo caso il contenuto di x viene
memorizzato nel regisro mem1
Le istruzioni qui sotto con (*) DEVONO ESSERE PRECEDUTE DALL'INDICE
------------------------------------------------------------------------------------------------------------
I/O = 20 PRINT 21 INPUT da 22 a 29 disp
------------------------------------------------------------------------------------------------------------
ARDUINO = 30 *PINPUT 31 *PIOUT 32 *DWHIGH 33 *DWLOW 34 *DREAD
35 *AREAD 36 *AWRITE 37 *DELAYn 38 *TONE 39 *NOTONE
------------------------------------------------------------------------------------------------------------
CONTROLLO = 40 XmaggioreY? 41 XminoreY? 42 X = Y 43 X maggiore 0? 44 Xminore 0?
45 *INCn 46 END 47 LOOP 48 RTN 49 NOP
MATEMATICHE = 50 (-) 51 (X) 52 (/) 53 (+) 54 CHS 55 Y^x 56 1/X 57 disp
58 SQRT 59 disp
------------------------------------------------------------------------------------------------------
CATASTA e VARIE = 60 DEL 61 ENTER 62 CLST (clr) 63 LASTX 64 XscambioY
65 RUOTA GIU' 66 CLX 67 *STOnn 68 *RCLnn 69 RUOTA SU R^
------------------------------------------------------------------------------------------------------
TRIGONOM e VARIE = 70 PI 71 SIN 72 COS 73 TAN 74 ASIN 75 ACOS
76 ATAN 77 disp 78 disp 79 disp
--------------------------------------------------------------------------------------------------------------
ESEGUI e VARIE = 80 SUB0 81 SUB1 82 SUB2 83 SUB3 84 SUB4 85 SUB5
86 disp 87 disp 88 *XEQnn 89 disp
--------------------------------------------------------------------------------------------------------------
LABEL e VARIE = 90 LBL0 91 LBL1 92 LBL2 93 LBL3 94 LBL4 95 LBL5
96 disp 97 disp 98 disp 99 ENDEND
--------------------------------------------------------------------------------------------------------------
*******************************************************************************
I programmi si scrivono semplicemente digitando il codice relativo alla funzione,
si dovranno immettere sempre 2 caratteri per digitare uno si scrive "01".
L'EDITOR visualizza un numero progressivo (linea programma).
Una volta scritto il programma si potrà controllare scorrendo (tasto 1 avanti) - (tasto 3 indietro) le linee di programma.
E' possibile correggere gli errori.
Finito il controllo è possibile salvare il programma in memoria.
(in questo modo ad una successiva accensione si potrà utilizzare il programma)
Qui sotto il loop principale del programma.
//**************************************************************
void loop()
{
inizializzazione(); // inizializzazione
iniarduino();
// scelte iniziali calcolatrice o arduQuadro menu
arduino();
while(arduQuadro == true)
{
nuovoprog(); // scelta se NEW (scrivere nuovo programma )
//oppure OLD programma in RAM
// finito la registrazione
// del programma o il caricamento da RAM
controllo(); // Si esegue il controllo e correzione
costanti(); // Possiamo inserire dati nei registri
stringhe(); // per inserimento stringhe
// pronto e si mette in attesa pressione tasto
pronto();
tasto();
// Esegue il programma utente
progUtente();
// uscita dal programma utente
fineprog();
}
// esegue come calcolatrice diretta
if (calcRPN == true) {uscitacalc = false;calcolatrice();}
}
//**** END LOOP ************************************
//***************************************************
dopo l'inizializzazione apparirà sul display questo menù, che ci chiede di scegliere fra
CALC (calcolatrice manuale) oppure arduQ ( uso in programmazione )
void arduino()
{
//stringaMenu0 = String("1234567890123456");
stringaMenu0 = String("arduinoQuadro-13");
stringaMenu1 = String("1=CALC 3= arduQ ");
sceltemenu();
if (old == true){arduQuadro = true; calcRPN = false;} // si programma come arduQuadro
else {arduQuadro = false; calcRPN = true;}/// si usa come calcolatrice
}
// con questa si esegue un programma esistente
// si corregge un programma esistente
// oppure si sceglie di scriverne uno nuovo
void nuovoprog()
{
stringaMenu0 = String("Menu programma ");
stringaMenu1 = String("1=NEW - 3=OLD"); **A
sceltemenu();
if (old == true){leggiprog();} // con old a true si legge il programma dalla EPROM
if (old == false) {scritturaprog();} // con old false si scrive nuovo programma
}

(si scrivono i codici delle istruzioni ogni codice 2 cifre )
in questo caso si vedrà sul display
lcd.print("C.. ");
ed ad ogni codice inserito il numero linea ed il codice
Per finire premere 2 volte il tasto (2F)
Secelta **A
OLD il programma prosegue richiamando il programma esistente e riprende dal controllo e correzione.
Alla richiesta di controllo possiamo scegliere se effettuare un controllo del programma in memoria oppure no.
Con l'editor possiamo scorrere le istruzioni avanti tasto (1) indietro tasto (3)
Possiamo correggere un'istruzione errata, ed è possibile inserire istruzioni.
( vedi più avanti spiegazioni uso editor )
Alla fine del controllo possiamo salvare il programma corretto
appare il messaggio " Salva in RAM"
Dopo questa fase possiamo inserire dati.
Per inserire dati nella catasta si opera in modo consueto come con la calcolatrice in modo diretto
Per inserire i dati nelle memorie utente occorre inserire il dato in X e nella linea visore il numero da 1 a 19 del registro che vogliamo utilizzare.
Con l'editor possiamo scorrere le istruzioni avanti tasto (1) indietro tasto (3)
Possiamo correggere un'istruzione errata, ed è possibile inserire istruzioni.
( vedi più avanti spiegazioni uso editor )
Alla fine del controllo possiamo salvare il programma corretto
appare il messaggio " Salva in RAM"
Dopo questa fase possiamo inserire dati.
Per inserire dati nella catasta si opera in modo consueto come con la calcolatrice in modo diretto
Per inserire i dati nelle memorie utente occorre inserire il dato in X e nella linea visore il numero da 1 a 19 del registro che vogliamo utilizzare.
void costanti()
{
stringaMenu0 = String("Ins. Dati ? ");

sceltemenu();
if (old == true){return;} // salta inserimento dati
// inseimento dati valori
dati = true;
while ( dati == true)
{
aggiornadisplay(); // sub che aggiona il display
tasto();
insertdati();
if (codice == 62){dati = false;}
}
lcd.clear();
lcd.setCursor(0,0);
lcd.print("OK dati inseriti");
delay (1000);
}
Una volta risposto SI (1) alla richiesta di inserire dati viene visualizzato la riga X e sotto la riga visore come nell'uso come calcolatrice.
Si può inserire le cifre e con Enter si passano nella catasta operativa ( si possono usare per l'inserimento i registri della catasta ( x,y,z,t,u) .... logicamente il programma dovrà essere scritto per utilizzarli tenendo conto delle operazioni in catasta.
E' possibile anche inserire dati nei registri dedicati all'utente da 1 a 19 ( sono float).
Per inserire un dato in questi registri si procede così:
_ Prima si inserisce nel registro X con Enter.
_ Poi si inserisce nella riga visore il numero del registro da 1 a 19 senza premere Enter
_ Quindi premere il tasto (+) più ( apparirà " OK " )
continuare così per tutti i dati da inserire
_ alla fine premere il tasto 2F con il quale si esce da inserimento dati, appare il messaggio
" OK dati inseriti"
Il programma chiederà se inserire stringhe.... ( per ora Una stringa )
Questa funzione è molto limitata si possono introdurre i codici ASCII ( solo minori di 99)
per formare una stringa MAX 16 caratteri che utilizzeremo nella PRINT
Questa funzione non è molto funzionale (ma la tastiera disponibile è limitata) penso di realizzare una versione con una tastiera più dotata e quindi semplificando l'immissione dei programmi e delle stringhe.
dopo questa fase il programma attende la pressione di un tasto e si avvia.
(si può lanciare in esecuzione anche un loop continuo che si ferma solo togliendo alimentazione o premendo il reset di arduino)
Al termine del programma UTENTE si potrà scegliere se continuare in programmazione o passare alla calcolatrice in uso manuale (STOP)
void fineprog()
{
stringaMenu0 = String("Fine programma");
stringaMenu1 = String("1=STOP 3=CONT"); // si stop
sceltemenu();
if (si == true) {calcRPN = true; arduQuadro = false;}
}
//*************************************************
Enter: Introduce in x quanto è contenuto sul "visore" e fa salire il resto della catasta, quello che era in x sale in y, il contenuto di y sale in z, il contenuto di z sale in t.
Del Cancella il contenuto del visore.
Qui descrivo l'uso diretto della calcolatrice
Uso diretto si usano le funzioni dirette e seconde ( 2F)
In modo del tutto analogo al precedente post.
Per uscire dall'uso diretto premere 2 volte il tasto 2F.
Indice delle funzioni e loro uso:
----------------------------------------------------------------------
Funzioni dirette
----------------------------------------------------------------------
Somma, sottrazione, : Si introducono i due operandi in Y ed X quindi si preme il tasto relativo alla funzione, il risultato viene posto in X.Enter: Introduce in x quanto è contenuto sul "visore" e fa salire il resto della catasta, quello che era in x sale in y, il contenuto di y sale in z, il contenuto di z sale in t.
Del Cancella il contenuto del visore.
F2 Tasto seconda funzione abilita la seconda funzione.
Questo tasto è utilizzato anche per altre funzioni nel programma (vedi note per F2)
----------------------------------------------------------------------------------
Funzioni seconde
----------------------------------------------------------------------------------
moltiplicazione, divisione: Si introducono i due operandi in Y ed X quindi si preme il tasto relativo alla funzione, il risultato viene posto in X
Sin, Tan, Cos : Restituiscono in X, il valore seno, tangente, coseno dell'angolo in Radianti contenuto in X.
Sqrt : Esegue la radice quadrata del contenuto in X, pone il risultato in X.
Y^x : Eleva a potenza , introdurre in Y il valore, in X l'esponente, il risultato è posto in X.
CHS : Cambio segno, cambia il segno ad X.
STO: Memorizza in un registro utente ( da 1 a 19) il contenuto di X, immettere in X il valore da memorizzare ( potrebbe anche essere il risultato di precedenti operazioni) poi nel visore scrivere il registro dove si vuole memorizzare (1 a 19) quindi premere il tasto funzione. Il contenuto di x rimane in x e viene duplicato nel registro indicato.
La stessa modalità si può utilizzare in programmazione:
1 inserire indice es : 01
2 inserire il codice : 67
queste due righe di programma memorizzano il contenuto di x nel registro utente 01.
RCL: Richiama in X il contenuto del registro ( da 1 a 19), immettere nel visore il numero del registro e premere il tasto funzione, in X avremo il contenuto del registro richiesto, il registro rimane invariato, nel registro lastx viene prima salvato il contenuto precedente di X.
La stessa modalità si può utilizzare in programmazione:
1 inserire indice es : 02
2 inserire il codice : 68
queste due righe di programma richiamano in x il valore contenuto nel registro indice 02.
FIX: Si possono impostare il numero dei decimali visualizzati ( da 0 a 5 ), scrivere in visore il numero da 0 a 5 e premere il tasto funzione. Di default ho posto a 4 i decimali.
Non programmabile
lastx: Recupera in X il contenuto precedente ad una operazione, il contenuto di X viene spostato in Y.
Utile per recuperare in caso di operazioni errate.
X_Y: Scambio X con Y, Insieme alla rotazione della catasta si può cambiare l'ordine degli operandi in catasta.
R! : Ruota giù, la catasta viene fatta ruotare y in x, z in y, t in z, x in t. Ad ogni pressione ruota fino a tornare nella situazione iniziale, utile per rivedere tutto il contenuto della catasta, ed eventualmente utilizzando lo scambio cambiarne la disposizione.
XEQ : Questa funzione richiama ed esegue funzioni o programmi, si scrive nel visore il numero della funzione e si preme il tasto XEQ, prima si dovrà immettere in catasta i valori richiesti dalla funzione e o programma rispettandone anche l'ordine. In uscita avremo la catasta aggiornata con i risulati.
Possono essere usati anche i registri utente che la funzione e/o programma possono utilizzare come input e/o come output.
La stessa modalità si può utilizzare in programmazione:
------------------------------------------------------------------------------------------
Riporto qui per maggior chiarezza le funzioni richiamabili.
da 1 a 3 arco seno di x, arco tangente di x, arcoseno di x, restituiscono in x l'angolo
relativo al valore trovato in x l'angolo è espresso in RADIANTI, si utilizza semplicemente
le funzioni della libreria. In Lastx si conserva il valore di partenza.
In programmazione queste si possono chiamare più semplicemente con il codice relativo:
4 e 5 converte angoli sesagesimali in sessadecimali e viceversa
6 richiama la costante PI (pigreco) anche questa nella libreria.
In programmazione si può digitare il codice 71:
9 cancella i registri catasta e visore, cancella anche lastx.
Queste funzioni usano due registi per input e output ( x , y).
10 da rettangolari a polari inserire in x la coordinata x, ed in y la coordinata y.
restituisce in y la distanza
restituisce in x angolo in RADIANTI
11 da polari a rettangolari inserire in x l'angolo alfa in RADIANTI
inserire in y la magnitudine o distanza.
restituisce le coordinate in x e y.
12 cancella memorie utente (tutte) non ha bisogno di input.
13 attiva o disattiva la notazione scientifica (ma se un numero è troppo grande
o troppo piccolo per essere visualizzato cambia automaticamente).
14 EEX entrata con l'esponente, per l'input di numeri con mantissa ed esponente
introdurre la mantissa in y e l'esponente in x.
15 e 16 logaritmo naturale ed e^x.
17 e 18 logaritmo in base 10 ed 10^x.
19 fattoriale di x ( x numero intero da 1 a 30 MAX), restituisce in x il fattoriale.
20 e 21 da RADIANTI a centesimali e viceversa.
-------------
**** P R O G R A M M A Z I O N E ****
Descrizione delle funzioni programmabili e relativi codici:
Codici da 1 a 19 --- INDICI si inseriscono nel programma prima della funzione che ne farà uso.
20 --- PRINT scrive sul display nella prima riga X= ...... e sotto la stringaUTENTE (che può anche essere vuota)
21 --- INPUT si possono inserire dati nei registri e nella catasta.
-----------------------------------------------------------------------------------------------------
Istruzioni funzioni "Arduino"
Istruzioni funzioni "Arduino"
30 --- PINPUT deve essere preceduta dal numero del pin da porre come Input.
31 --- PIOUT deve essere preceduta dal numero del pin da porre come Output.
32 --- DWHIGH deve essere preceduta dal numero del pin da porre ALTO (1).
33 --- DWLOW deve essere preceduta dal numero del pin da porre BASSO (0).
34 --- DREAD legge il valore 0/1 del pin indicato nell'istruzione che la precede.
35 -- AREAD legge il valore analogico del pin indicato nell'istruzione che la precede.
36 -- AWRITE scrive sul pin indicato il valore (0 -255) contenuto in x.
37 -- DELAY n scrivere prima uno dei seguenti indici :
1 = 5 mms, 2= 10, 3= 50, 4= 250, 5=500, 6 = 1000 mms
poi il codice 37 ed avremo un Delay del tempo indicato
per tempi diversi ripetere l'istruzione
38 -- TONE TONE (PIN,FREQUENZA,DURATA)
/ indirizzo per pin
nel regx la frequenza (intero)
// in regy se zero ( per fermare occorre la NOTONE)
// oppure inserire in y la durata in mms.
39 -- NOTONE per fermare la TONE indicare il pin da fermare.
(prima di attivare un pin occorre fermare il pin che esegue TONE)
--------------------------------------------------------------------------------------------------------------
Istruzioni di controllo ( IF )
Queste istruzioni eseguono il controllo,
il programma salta l'istruzione successiva SE VERA la condizione.
I controlli sono: 40 XmaY , 41 XmiY , 42 X=Y , 43 Xma0 , 44 Xmi0 .
45 -- INCn per simulare il for. Inserire un codice da 1 a 6 seguito dalla istruzione INCn (45).
Questa istruzione mette a disposizione 6 variabili di tipo intero,
inc1, inc2 ecc.. In fase di inserimento dati del programma queste
variabili si inizializzano con un valore da raggiungere ( target).
Nello stesso momento si pone a 0 le corrispondenti variabili
cont1, cont2 ecc.. che serviranno per il conteggio.
Tasto ( - ) durante la fase di Inserimento Dati
( vedi spiegazione tasti funzione più sotto)
Nella fase di elaborazione la variabile cont(n) viene incrementata di 1 ad ogni
ciclo, nel registro regx viene posto il cont attuale, ed in regy viene posto inc(n).
Ora si può fare un controllo X con Y per verificare se il target è stato raggiunto.
46 -- END con questa si indica la fine del programma. Quando il programma trova questa istruzione esce dall'esecuzione ed è disponibile per l'uso diretto.
47 -- LOOP questa istruzione se inserita crea un loop continuo il programma non termina.
La prima esecuzione del programma parte sempre dall'istruzione 0, se la loop è inserita come prima istruzione il programma riparte sempre da 0, altrimenti dopo la prima esecuzione le successive ripartono dalla riga loop.
Questo rende possibile eseguire un loop successivo ad una fase simile ad un setup.
48 -- RTN istruzione di fine subroutine.
Il programma torna alla riga successiva alla chiamata della corrispondente label.
Se questa istruzione non viene inserita il programma prosegue fino all'ultima istruzione.
49 -- NOP non operazioni
-------------------------------------------------------------------------------------------------------------------------
Matematiche
50 (-), 51 ( * ), 52 ( / ), 53 ( + )
54 -- CHS cambia segno al registro regx.
55 -- Y^x eleva il contenuto di regy alla potenza indicata in regx il risultato in regx.
56 -- 1/X uno su X ( esegue l'operazione 1/x il risultato nel regx)
57 -- disp
58 -- SQRT salva X in lastx e poi calcola la radice quadrata di X risultato in regx .
59 -- disp
-------------------------------------------------------------------------------------------------------------------------
Operazioni catasta.
60 -- DEL cancella "Visore" ( linea per inserimento dati ).
61 -- ENTER fa salire la catasta operativa ed introduce il contenuto del "Visore" nel registro
regx poi azzera il visore.
62 -- CLST cancella la catasta compreso lastx ed il visore.
63 -- LASTX nel registro regx ritorna il valore di lastx e sale tutta la catasta.
64 -- X_Y scambio fra regx e regy.
65 -- R! ruota la catasta GIU'
66 -- CLX azzera il registro x (prima salva il contenuto nel registro lastx)
67 -- STOnn introduce nel registro nn (indicato da indice ) il contenuto del regx.
68 -- RCLnn richiama dal registro nn (indicato da indice ) e pone il contenuto nel registro regx facendo salire la catasta.
69 -- R^ ruota la catasta SU
-------------------------------------------------------------------------------------------------------------------------
Trigonometriche
70 -- PI costante PI (pigreco) viene richiamate nel regx. (prima salva il contenuto di x in lastx)
71 -- SIN prima salva in lastx il registro x e poi calcola la funzione.
72 -- COS prima salva in lastx il registro x e poi calcola la funzione.
73 -- TAN prima salva in lastx il registro x e poi calcola la funzione.
74 -- ASIN prima salva in lastx il registro x e poi calcola la funzione.
75 -- ACOS prima salva in lastx il registro x e poi calcola la funzione.
76 -- ATAN prima salva in lastx il registro x e poi calcola la funzione.
--------------------------------------------------------------------------------------------------------------------------
Chiamata a SUB
da codice 80 a 85 SUB0, SUB1, SUB2, SUB3, SUB4, SUB5.
Questi codici indirizzano il programma sulla linea della relativa label.
Label da 90 a 95 LBL0, LBL1, LBL2,LBL3, LBL4, LBL5.
Quando il programma si sposta sulla label chiamata esegue le funzioni fino a trovare RTN
quando trova RTN torna all'istruzione successiva che ha chiamato la SUB, altrimenti prosegue fino alla fine del programma.
All'interno di una SUB è possibile chiamare altre sub fino ad un massimo di 6 nidificazioni.
--------------------------------------------------------------------------------------------------------------------------
88 -- XEQnn con questa si può chiamare una funzione od un programma.
Impostare nel visore il numero della funzione e/o programma e chiamare il
codice 88 (nella catasta o nei registri dovranno esserci già impostati i relativi dati per il calcolo.
Per esempio (funzione R-P da rettangolari a polari), posso impostare la coordinata X e la coordinata Y nei rispettivi registri poi nel programma indicherò
10 (numero di questa funzione) seguito da 88 ed avrò come risultato
in regy il vettore distanza, ed in regx l'angolo in radianti.
Questo codice XEQnn in pratica aggiunge molte altre possibili funzioni,
io ne ho preparate alcune ma altre possono essere fatte dall'utente per sua
comodità o per scopi specifici.
99 -- ENDEND fine del listato di programma (ultima istruzione).
-------------------------------------------------------------------------------------------------------------------------
Il listato per Arduino che allego è funzionante ma non ho testato tutte le possibilità.
La gestione degli errori nei programmi utente non è stata implementata.
In caso di errori o loop infiniti rimane solo la possibilità di reset.
Questo il messaggio dell' IDE dopo la compilazione.
Lo sketch usa 26.478 byte (82%) dello spazio disponibile per i programmi. Il massimo è 32.256 byte.
Le variabili globali usano 1.200 byte (58%) di memoria dinamica, lasciando altri 848 byte liberi per le variabili locali. Il massimo è 2.048 byte.
Sergio.
Istruzioni di controllo ( IF )
Queste istruzioni eseguono il controllo,
il programma salta l'istruzione successiva SE VERA la condizione.
I controlli sono: 40 XmaY , 41 XmiY , 42 X=Y , 43 Xma0 , 44 Xmi0 .
45 -- INCn per simulare il for. Inserire un codice da 1 a 6 seguito dalla istruzione INCn (45).
Questa istruzione mette a disposizione 6 variabili di tipo intero,
inc1, inc2 ecc.. In fase di inserimento dati del programma queste
variabili si inizializzano con un valore da raggiungere ( target).
Nello stesso momento si pone a 0 le corrispondenti variabili
cont1, cont2 ecc.. che serviranno per il conteggio.
Tasto ( - ) durante la fase di Inserimento Dati
( vedi spiegazione tasti funzione più sotto)
Nella fase di elaborazione la variabile cont(n) viene incrementata di 1 ad ogni
ciclo, nel registro regx viene posto il cont attuale, ed in regy viene posto inc(n).
Ora si può fare un controllo X con Y per verificare se il target è stato raggiunto.
46 -- END con questa si indica la fine del programma. Quando il programma trova questa istruzione esce dall'esecuzione ed è disponibile per l'uso diretto.
47 -- LOOP questa istruzione se inserita crea un loop continuo il programma non termina.
La prima esecuzione del programma parte sempre dall'istruzione 0, se la loop è inserita come prima istruzione il programma riparte sempre da 0, altrimenti dopo la prima esecuzione le successive ripartono dalla riga loop.
Questo rende possibile eseguire un loop successivo ad una fase simile ad un setup.
48 -- RTN istruzione di fine subroutine.
Il programma torna alla riga successiva alla chiamata della corrispondente label.
Se questa istruzione non viene inserita il programma prosegue fino all'ultima istruzione.
49 -- NOP non operazioni
-------------------------------------------------------------------------------------------------------------------------
Matematiche
50 (-), 51 ( * ), 52 ( / ), 53 ( + )
54 -- CHS cambia segno al registro regx.
55 -- Y^x eleva il contenuto di regy alla potenza indicata in regx il risultato in regx.
56 -- 1/X uno su X ( esegue l'operazione 1/x il risultato nel regx)
57 -- disp
58 -- SQRT salva X in lastx e poi calcola la radice quadrata di X risultato in regx .
59 -- disp
-------------------------------------------------------------------------------------------------------------------------
Operazioni catasta.
60 -- DEL cancella "Visore" ( linea per inserimento dati ).
61 -- ENTER fa salire la catasta operativa ed introduce il contenuto del "Visore" nel registro
regx poi azzera il visore.
62 -- CLST cancella la catasta compreso lastx ed il visore.
63 -- LASTX nel registro regx ritorna il valore di lastx e sale tutta la catasta.
64 -- X_Y scambio fra regx e regy.
65 -- R! ruota la catasta GIU'
66 -- CLX azzera il registro x (prima salva il contenuto nel registro lastx)
67 -- STOnn introduce nel registro nn (indicato da indice ) il contenuto del regx.
68 -- RCLnn richiama dal registro nn (indicato da indice ) e pone il contenuto nel registro regx facendo salire la catasta.
69 -- R^ ruota la catasta SU
-------------------------------------------------------------------------------------------------------------------------
Trigonometriche
70 -- PI costante PI (pigreco) viene richiamate nel regx. (prima salva il contenuto di x in lastx)
71 -- SIN prima salva in lastx il registro x e poi calcola la funzione.
72 -- COS prima salva in lastx il registro x e poi calcola la funzione.
--------------------------------------------------------------------------------------------------------------------------
Chiamata a SUB
da codice 80 a 85 SUB0, SUB1, SUB2, SUB3, SUB4, SUB5.
Questi codici indirizzano il programma sulla linea della relativa label.
Label da 90 a 95 LBL0, LBL1, LBL2,LBL3, LBL4, LBL5.
Quando il programma si sposta sulla label chiamata esegue le funzioni fino a trovare RTN
quando trova RTN torna all'istruzione successiva che ha chiamato la SUB, altrimenti prosegue fino alla fine del programma.
All'interno di una SUB è possibile chiamare altre sub fino ad un massimo di 6 nidificazioni.
--------------------------------------------------------------------------------------------------------------------------
88 -- XEQnn con questa si può chiamare una funzione od un programma.
Impostare nel visore il numero della funzione e/o programma e chiamare il
codice 88 (nella catasta o nei registri dovranno esserci già impostati i relativi dati per il calcolo.
Per esempio (funzione R-P da rettangolari a polari), posso impostare la coordinata X e la coordinata Y nei rispettivi registri poi nel programma indicherò
10 (numero di questa funzione) seguito da 88 ed avrò come risultato
in regy il vettore distanza, ed in regx l'angolo in radianti.
Questo codice XEQnn in pratica aggiunge molte altre possibili funzioni,
io ne ho preparate alcune ma altre possono essere fatte dall'utente per sua
comodità o per scopi specifici.
99 -- ENDEND fine del listato di programma (ultima istruzione).
-------------------------------------------------------------------------------------------------------------------------
Tasti con funzioni multiple:
F2 ( tasto seconda funzione )
Se la calcolatrice è in uso diretto con la pressione del tasto si passa alle funzione secondarie dei tasti
( * ) , ( / ), SIN, COS ecc....
Premendo mentre siamo in 2F ( si vede dal visore con il 2 a sinistra) si esce dalla calcolatrice manuale e si riparte dal menù iniziale con la richiesta di scegliere fra arduQ o CALC.
Quando siamo in programmazione nell'EDITOR premendo F2 si indica la fine di scrittura del programma e si passa alla fase successiva.
Quando siamo in "Controllo" serve per uscire.
In fase di inserimento dati o stringhe serve per uscire.
-------------------------------------------------------------------------------------------------------------------------
Tasto ( - ) durante la fase controllo.
Si può correggere la linea di programma.
_ posizionarsi sulla riga da correggere
_ premere il tasto - (meno) e poi inserire il codice corretto, apparirà correzione OK.
_ Questo serve solo a sostituire una istruzione errata, il resto del programma rimane invariato.
_ Se serve cancellare la riga è sufficiente inserire una NOP ( 49) che non altera il programma.
_ posizionarsi sulla riga da correggere
_ premere il tasto - (meno) e poi inserire il codice corretto, apparirà correzione OK.
_ Questo serve solo a sostituire una istruzione errata, il resto del programma rimane invariato.
_ Se serve cancellare la riga è sufficiente inserire una NOP ( 49) che non altera il programma.
Tasto ( + ) durante la fase di controllo.
Con questo tasto si può inserire una nuova linea di programma. Tutto il programma si sposta dalla riga inserita in poi fino all'ultima.
_ posizionarsi con i tasti 1-3 sulla riga dove vogliamo inserire nuovo codice
_ si preme (+ )
_ ci chiede d'impostare il nuovo codice da inserire, inseriamo il codice
_ quindi sposta tutte le linee aggiungendo una riga al programma.
_ segnala con messaggio "correzione ok"
Per vedere la correzione spostarsi con i tasti 1-3.
_ posizionarsi con i tasti 1-3 sulla riga dove vogliamo inserire nuovo codice
_ si preme (+ )
_ ci chiede d'impostare il nuovo codice da inserire, inseriamo il codice
_ quindi sposta tutte le linee aggiungendo una riga al programma.
_ segnala con messaggio "correzione ok"
Per vedere la correzione spostarsi con i tasti 1-3.
In fase di controllo i tasti ( 1 ) e ( 3) servono per scorrere le istruzioni avanti e indietro.
-------------------------------------------------------------------------------------------------------------------------
Tasto ( + ) durante la fase di Inserimento Dati ( STOnn )
Dopo aver inserito in X il dato da memorizzare inserire in visore il registro desiderato e quindi
premere ( + ), nel registro nn viene inserito il valore.
Tasto ( - ) durante la fase di Inserimento Dati ( INCn)
Si può inserire il valore target del FOR in X ed nel visore il numero da 1 a 6 dei cicli possibili
poi premere il tasto ( - ).
Usare valori interi in ogni caso i registri utilizzati sono interi.
--------------------------------------------------------------------------------------------------------------------------
Programmi UTENTE
La programmazione con i codici qui proposta non è il massimo di semplicità ed immediatezza,
ma ho cercato di rendere disponibili le opzioni più comuni in un linguaggio di programmazione.
Le linee di programma attualmente previste sono 100.
Le label sono 6 ( possono essere chiamate più volte)
Le label LBL sono solo 6 e non possono essere inserite più volte nel programma.
Da una SUB si può chiamare altra SUB ma non se stessa.
Le IF di controllo possono essere fatte solo fra X e Y oppure fra X e 0.
Se il risultato del controllo è VERO salta l'istruzione successiva.
Il ciclo FOR è semplificato dalla INCn che mette a disposizione 6+6 variabili di tipo intero per il conteggio dei cicli.
Le variabili intere inc1, inc2, ...., inc6 contengono il valore da raggiungere, le variabili corrispondenti
con1, cont2, ... cont6 conterranno i valori incrementati, l'incremento è fisso di 1.
Per questi programmi occorre scrivere le varie istruzioni, poi scriversi i relativi codici, e poi inserirli.
Ho preparato alcuni esempi per meglio spiegare l'uso di questa calcolatrice.
Esempi di programmi in "codice99"
Considero che già utilizzate la calcolatrice in modo manuale ed abbiate ben chiaro come utilizzare la catasta operativa RPN.
In caso contrario date una lettura al precedente post
In caso contrario date una lettura al precedente post
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Questo esempio fa lampeggiare due led ed attiva il buzzer.
Si utilizzano i pin 8, e 10 per il led ed il pin 9 per il buzzer.
Prima si mettono in output i pin ( righe da 0 a 5 ) si indica il numero del pin seguito dall'istruzione PIOUT.
alla riga 6 si trova la label 0 LBL0 (codice 90)
Poi si accende un led si esegue un TONE ( in fase di inserimento dati ho introdotto 600 in Y ( durata del Tone, e 800 in X frequenza.
L'istruzione 12 esegue un Delay di 500mms
Quindi l'istruzione 14 spenge il led.
Poi si fanno le stesse cose con il secondo led.
Quindi all'istruzione 23 si trova la SUB0 che indirizza il programma sulla LBL0 riga 6
si entra così in LOOP che ripete le stesse istruzioni fino al reset della calcolatrice.
Allego un piccolo video dimostrativo.
Esempio di uso delle sub.
Uso i due led collegati ai pin 8 e 10.
Il programma del tutto simile al precedente serve solo a dimostrare l'uso delle sub.
La sub1 (LBL1 riga 10) fa accendere e spengere il led collegato al pin 8.
All'interno della sub1 viene chiamata la sub2 (LBL2 riga 21), questa sub fa accendere e spengere il led collegato al pin 10.
La sub2 quando trova RTN ritorna alla sub1 e a sua volta quando la sub1 trova RTN torna al programma principale.
IL programma principale continua eseguendo il loop fra la riga ( 4 LBL0 e la riga 8 SUB0).
In questi due sketch ho utilizzato un loop continuo ( per uscire occorre il reset della calcolatrice.)
Nel prossimo sketch faremo eseguire un numero determinato di cicli.
Qui si utilizza la funzione INCn che simula il FOR .
Il programma aggiunge rispetto al precedente 3 istruzioni
6 01 01 Questa indica quale INCn useremo
7 INCn 45 ad ogni passaggio la variabile cont1 viene incrementata
8 X=Y? 42 controlla se abbiamo raggiunto il target immesso nella fase ins dati.
con queste istruzioni si esegue il programma per un numero di volte da noi voluto
(nel campo int )
Arrivati al numero scelto il programma termina.
Se si esegue una seconda volta il programma occorre reinserire il valore target nella fase Inserimento dati.
La funzione INCn vista sopra può essere fatta anche con istruzioni in codice99 con qualche istruzione in più.
Vediamo il diagramma di flusso.
In questo sketch si legge un pin analogico A0 il valore letto va in X viene confrontato con il valore che abbiamo in Y (inserito nella fase "Inserimento dati" ) e se maggiore esegue l'istruzione successiva quindi torna a leggere un nuovo valore, questa fase si ripete fino a quando il valore X non risulta minore di Y ( loop corto).
Quando la luce diminuisce e X risulta minore del valore immesso in Y salta l'istruzione e prosegue accendendo il led e tornando alla partenza e così rimane fino a quando non cambia ulteriormente la luce ambiente ed il valore di X risulta MAGGIORE di Y.
Lo sketch ripete il loop fino al reset della calcolatrice.
Se avete salvato il programma nella EEPROM potrete richiamarlo e magari provare ad inserire in Y un valore diverso come soglia di luce.
Credo che con gli esempi fatti si possa capire come utilizzare questa calcolatrice.
Sul mio canale YouTube trovate un video su questa calcolatrice.
Si utilizzano i pin 8, e 10 per il led ed il pin 9 per il buzzer.
Prima si mettono in output i pin ( righe da 0 a 5 ) si indica il numero del pin seguito dall'istruzione PIOUT.
alla riga 6 si trova la label 0 LBL0 (codice 90)
Poi si accende un led si esegue un TONE ( in fase di inserimento dati ho introdotto 600 in Y ( durata del Tone, e 800 in X frequenza.
L'istruzione 12 esegue un Delay di 500mms
Quindi l'istruzione 14 spenge il led.
Poi si fanno le stesse cose con il secondo led.
Quindi all'istruzione 23 si trova la SUB0 che indirizza il programma sulla LBL0 riga 6
si entra così in LOOP che ripete le stesse istruzioni fino al reset della calcolatrice.
Allego un piccolo video dimostrativo.
Esempio di uso delle sub.
SKETCH – lampeggio di due led utilizzando due sub (SECONDO) | |||||
Riga | istruzione | codice | note | ||
0 | 8 | 8 | pin digitale 8 collegato al led | ||
1 | PIOUT | 31 | il pin 8 in OUTPUT | ||
2 | 10 | 10 | pin digitale 10 collegato al led | ||
3 | PIOUT | 31 | il pin 10 in OUTPUT | ||
4 | LBL0 | 90 | Label 0 | ||
5 | SUB1 | 81 | SUB 1 SI ESEGUE LA Sub va alla LBL1 | ||
6 | NOP | 49 | inserite per indicare possibili altre istruzioni | ||
7 | NOP | 49 | |||
8 | SUB0 | 80 | SUB 0 ( va alla riga 4 codice 90 ) LOOP | ||
9 | END | 46 | END programma | ||
10 | LBL1 | 91 | inizio SUB1 | ||
11 | 8 | 8 | |||
12 | DWHIGH | 32 | il pin 8 si porta alto HIGH | ||
12 | 5 | 5 | valore per delay ( 500 mms) | ||
14 | DELAY | 37 | esegue DELAY | ||
15 | 8 | 8 | |||
16 | DWLOW | 33 | il pin 8 si porta basso LOW | ||
17 | SUB2 | 82 | SUB2 esegue la sub va alla LBL2 | ||
18 | NOP | 49 | inserite per indicare possibili altre istruzioni | ||
19 | NOP | 49 | |||
20 | RTN | 48 | Torna a riga seguente la SUB1 (6) | ||
21 | LBL2 | 92 | |||
22 | 10 | 10 | |||
23 | DWHIGH | 32 | il pin 10 si potra alto HIGH | ||
24 | 5 | 5 | |||
25 | DELAY | 37 | esegue DELAY | ||
26 | 10 | 10 | |||
27 | DWLOW | 33 | il pin 10 si porta basso LOW | ||
28 | RTN | 48 | Torna a riga seguente la SUB2 (18) | ||
Uso i due led collegati ai pin 8 e 10.
Il programma del tutto simile al precedente serve solo a dimostrare l'uso delle sub.
La sub1 (LBL1 riga 10) fa accendere e spengere il led collegato al pin 8.
All'interno della sub1 viene chiamata la sub2 (LBL2 riga 21), questa sub fa accendere e spengere il led collegato al pin 10.
La sub2 quando trova RTN ritorna alla sub1 e a sua volta quando la sub1 trova RTN torna al programma principale.
IL programma principale continua eseguendo il loop fra la riga ( 4 LBL0 e la riga 8 SUB0).
In questi due sketch ho utilizzato un loop continuo ( per uscire occorre il reset della calcolatrice.)
Nel prossimo sketch faremo eseguire un numero determinato di cicli.
Qui si utilizza la funzione INCn che simula il FOR .
Il programma aggiunge rispetto al precedente 3 istruzioni
6 01 01 Questa indica quale INCn useremo
7 INCn 45 ad ogni passaggio la variabile cont1 viene incrementata
8 X=Y? 42 controlla se abbiamo raggiunto il target immesso nella fase ins dati.
con queste istruzioni si esegue il programma per un numero di volte da noi voluto
(nel campo int )
Arrivati al numero scelto il programma termina.
Se si esegue una seconda volta il programma occorre reinserire il valore target nella fase Inserimento dati.
SKETCH – lampeggio di due led utilizzando due sub ( TERZO) | |||||
Riga | istruzione | codice | note | ||
0 | 8 | 8 | pin digitale 8 collegato al led | ||
1 | PIOUT | 31 | il pin 8 in OUTPUT | ||
2 | 10 | 10 | pin digitale 10 collegato al led | ||
3 | PIOUT | 31 | il pin 10 in OUTPUT | ||
4 | LBL0 | 90 | Label 0 | ||
5 | SUB1 | 81 | SUB 1 SI ESEGUE LA Sub va alla LBL1 | ||
6 | 1 | 1 | si usa la INC 1 | ||
7 | INCn | 45 | ad ogni passaggio incrementa il contatore | ||
8 | X=Y? | 42 | controlla se abbiamo raggiunto il target | ||
9 | SUB0 | 80 | SUB 0 ( va alla riga 4 codice 90 ) LOOP | ||
10 | END | 46 | END programma | ||
11 | LBL1 | 91 | inizio SUB1 | ||
12 | 8 | 8 | |||
13 | DWHIGH | 32 | il pin 8 si porta alto HIGH | ||
14 | 5 | 5 | valore per delay ( 500 mms) | ||
15 | DELAY | 37 | esegue DELAY | ||
16 | 8 | 8 | |||
17 | DWLOW | 33 | il pin 8 si porta basso LOW | ||
18 | SUB2 | 82 | SUB2 esegue la sub va alla LBL2 | ||
19 | NOP | 49 | inserite per indicare possibili altre istruzioni | ||
20 | NOP | 49 | |||
21 | RTN | 48 | Torna a riga seguente la SUB1 (6) | ||
22 | LBL2 | 92 | |||
23 | 10 | 10 | |||
24 | DWHIGH | 32 | il pin 10 si potra alto HIGH | ||
25 | 5 | 5 | |||
26 | DELAY | 37 | esegue DELAY | ||
27 | 10 | 10 | |||
28 | DWLOW | 33 | il pin 10 si porta basso LOW | ||
29 | RTN | 48 | Torna a riga seguente la SUB2 (18) | ||
La funzione INCn vista sopra può essere fatta anche con istruzioni in codice99 con qualche istruzione in più.
Prova di funzionamento:
Utilizzate il pin digitale 09 per il LED ed il pin analogico A1 per collegare la fotoresistenza.
(nell'immagine qui sotto il filo verde è erroneamente posizionato sul pin A0 ) .
Dovrete inserire un valore in Y che corrisponda alla soglia di luce alla quale si deve accendere il led.
Vediamo il diagramma di flusso.
In questo sketch si legge un pin analogico A0 il valore letto va in X viene confrontato con il valore che abbiamo in Y (inserito nella fase "Inserimento dati" ) e se maggiore esegue l'istruzione successiva quindi torna a leggere un nuovo valore, questa fase si ripete fino a quando il valore X non risulta minore di Y ( loop corto).
Quando la luce diminuisce e X risulta minore del valore immesso in Y salta l'istruzione e prosegue accendendo il led e tornando alla partenza e così rimane fino a quando non cambia ulteriormente la luce ambiente ed il valore di X risulta MAGGIORE di Y.
Lo sketch ripete il loop fino al reset della calcolatrice.
Se avete salvato il programma nella EEPROM potrete richiamarlo e magari provare ad inserire in Y un valore diverso come soglia di luce.
SKETCH – simil WHILE (QUARTO) | |||||
Riga | istruzione | codice | note | ||
0 | 9 | 9 | pin digitale 9 collegato al led | ||
1 | PIOUT | 31 | il pin 8 in OUTPUT | ||
2 | LBL0 | 90 | Label 0 | ||
3 | 1 | 1 | PIN A1 | ||
4 | AREAD | 35 | legge il valore analogico sul pin A1 | ||
5 | X |
42 | in Y avremo impostato un valore (ES= 90) | ||
6 | SUB0 | 80 | SUB 0 ( va alla riga 2 codice 90 ) LOOP | ||
7 | 9 | 9 | pin digitale 9 collegato al led | ||
8 | DWHIGH | 32 | il pin 9 si porta alto HIGH | ||
9 | 5 | 5 | valore per delay ( 500 mms) | ||
10 | DELAY | 37 | esegue DELAY | ||
11 | 9 | 9 | pin digitale 9 collegato al led | ||
12 | DWLOW | 33 | il pin 9 si porta basso LOW | ||
13 | SUB0 | 80 | SUB 0 ( va alla riga 2 codice 90 ) LOOP | ||
14 | END | 46 | FINE PROGRAMMA | ||
15 |
Credo che con gli esempi fatti si possa capire come utilizzare questa calcolatrice.
Sul mio canale YouTube trovate un video su questa calcolatrice.
Il listato per Arduino che allego è funzionante ma non ho testato tutte le possibilità.
La gestione degli errori nei programmi utente non è stata implementata.
In caso di errori o loop infiniti rimane solo la possibilità di reset.
Questo il messaggio dell' IDE dopo la compilazione.
Lo sketch usa 26.478 byte (82%) dello spazio disponibile per i programmi. Il massimo è 32.256 byte.
Le variabili globali usano 1.200 byte (58%) di memoria dinamica, lasciando altri 848 byte liberi per le variabili locali. Il massimo è 2.048 byte.
Come si vede c'è ancora spazio per aggiunte e o modifiche allo sketch, sono graditi commenti o segnalazioni di errori.
Sergio.
Il listato dello sketch
/* ****************************
SERGIO & ADRIANO PRENLELOUP
23/12/2017
file= arduinoQuadro-14
--------------------------------------------------------------------------
Con questo sketch si realizza una calcolatrice programmabile, che potrà
fare calcoli diretti, programmi utente con funzioni matematiche e trigonometriche,
sono disponibili PIN DIGITALI E PIN ANALOGICI che possono essere utilizzati
per input output.
Si potrà scrivere un piccolo programma che potrà essere conservato in ram.
Una volta lanciata l'esecuzione il programma viene eseguito dall'interpetre.
E si potranno visualizzare risultati sul display LCD, immettere dati
dalla tastiera, e/o utilizzare i pin disponibili di Arduino.
In questo modo si realizza un "Arduino-arduino".
Queste le caratteristiche:
Programmazione diretta con la scrittura di piccoli programmi nel linguaggio
"Codice99".
Questo linguaggio appositamente preparato si basa su 99 codici che possono essere
scritti in ram e che successivamente l'interpetre utilizzerà per eseguire la relativa funzione.
Ad ogni codice corrisponde una funzione.
(Alcune funzioni avranno bisogno di più codici)
L'immissione del programma in ram avviene con un micro editor che consente
di scrivere il programma.
Rivederlo scorrendo le istruzioni e correggere errori.
Una volta scritto il programma potrà essere eseguito e/o salvato nella EEPROM
(salvandolo nella EEPROM rimane permanente fino alla cancellazione).
Questo arduino avrà alcuni registri speciali (catasta operativa)
X, Y, Z, T, U, lastX.
Ci saranno alcuni registri di memoria che i programmi utente potranno utilizzare.
//**********************************************************************************************************
FUNZIONI PROGAMMABILI E RELATIVI CODICI.
MEMORIE & INDICI = da 00 a 19 (questi codici vengono immessi prima della istruzione che li
utilizza. prima si imposta il numero e poi l'istruzione.
Es. prima 01 poi 67 (STOnn) in questo caso il contenuto di x viene
memorizzato nel regisro mem1
Le istruzioni qui sotto con (*) DEVONO ESSERE PRECEDUTE DALL'INDICE
------------------------------------------------------------------------------------------------------------
I/O = 20 PRINT 21 INPUT da 22 a 29 disponibili
------------------------------------------------------------------------------------------------------------
ARDUINO = 30 *PINPUT 31 *PIOUT 32 *DWHIGH 33 *DWLOW 34 *DREAD 35 *AREAD 36 *AWRITE
37 *DELAYn 38 *TONE 39 *NOTONE
------------------------------------------------------------------------------------------------------------
CONTROLLO = 40 X>Y? 41 X<Y? 42 X=Y? 43 X>0? 44 X<0? 45 *INCn 46 END 47 LOOP 48 RTN 49 NOP
------------------------------------------------------------------------------------------------------------
MATEMATICHE = 50 (-) 51 (X) 52 (/) 53 (+) 54 CHS 55 Y^x 56 1/X 57 disp 58 SQRT 59 disp
-------------------------------------------------------------------------------------------------------------
CATASTA & VARIE = 60 DEL 61 ENTER 62 CLST (clr) 63 LASTX 64 X<>Y 65 RUOTA GIU' R!
66 CLX 67 *STOnn 68 *RCLnn 69 RUOTA SU R^
--------------------------------------------------------------------------------------------------------------
TRIGONOM & VARIE = 70 PI 71 SIN 72 COS 73 TAN 74 ASIN 75 ACOS 76 ATAN 77 disp 78 disp 79 disp
--------------------------------------------------------------------------------------------------------------
ESEGUI & VARIE = 80 SUB0 81 SUB1 82 SUB2 83 SUB3 84 SUB4 85 SUB5 86 disp 87 disp 88 *XEQnn 89 disp
--------------------------------------------------------------------------------------------------------------
LABEL & VARIE = 90 LBL0 91 LBL1 92 LBL2 93 LBL3 94 LBL4 95 LBL5 96 disp 97 disp 98 disp 99 ENDEND
--------------------------------------------------------------------------------------------------------------
*********************************************************************************************
HARDWARE
Si utilizza Arduino UNO, tastierino 16 tasti, display lcd 16x2 (I2C)
Possibilità di alimentazione a batteria.
*********************************************************************************************
*/
//***************************************
// librerie incluse
//---------------------------------------
// E' inclusa anche da sistema la <maht.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <EEPROM.h>
//******************************************************************************************
// E D I T O R dei programmi
//------------------------------------------------------------------------------------------
/*
I programmi si scrivono semplicemente digitando il codice relativo alla funzione,
si dovranno immettere sempre 2 caratteri per digitare uno si scrive "01".
L'EDITOR visualizza un numero progressivo (linea programma).
L'eventuale inizializzazione di variabili o di costanti si utilizzerà la
funzione RCL con la quale si richiama il registro da 1 a 19.
Nella fase inserimento dati potremmo immettere questi valori.
Nell'inserimento dati possiamo utilizzare anche i registri della catasta,
tenendo conto delle operazioni che svolgerà il programma
*/
//********************************************************************
const byte righe = 4; // per keypad
const byte colonne = 4;
//********************************************************************
byte key; // contiene il codice tasto premuto
byte codice =0; // codice operativo calcolato a partire da key (codice asccii)
byte codProg = 0; // codici programma
byte indirizzo = 0; // per indirizzare le memorie, i pin, le sub.
int poscifra = 0;// tiene conto delle cifre
boolean sciee = false; // true visualizza in notazione scientifica
boolean stato = false; // per la calcolatrice ( seconda funzione dei tasti)
//---------------------------------------------------------------
boolean looProg = false; // se true esegue loop
boolean se = true; // per le funzion if
boolean xeq = true; // per inserimento codice in Xeq_nn
boolean dati = true; // si inseriscono i dati in costanti
boolean prog = true; // si predispone per la programmazione
boolean sub = true; // per eseguire le subroutin
boolean endProg = false; // fine sub o programma
boolean stopProg = false; // per fermare il loop
boolean old = false; // per segnalare programma già in memoria risposta no
boolean si = true; // risposta si nelle scelte
boolean gira = false; // per sapere se sta elaborando il programma false non elabora
boolean uscitacalc = false; // per uscire da caLCOLATRICE
boolean arduQuadro = false; // si lavora con arduino quadro se true
boolean calcRPN = false; // si lavora in calcolatrice se true
//-----------------------------------------------------------------
float k1 = 10000000;// numero massimo visualizzabile poi si passa in visualizz scie
float k0 = 0.00001; // numero decimale piu piccolo visualizzabile
// per l'inserimento dei numeri decimali
int pdec = 0; // punto decimale
int ndec =0; // conta decimali
int fix = 4; //decimali di default
//*************************************************************************
// codici tastierino
//*************************************************************************
byte chiave [colonne][righe] =
{
{49,50,51,43}, // 1 2 3 +, *, sto, ins-linea
{52,53,54,45}, // 4 5 6 -, /, inc, corr-linea
{55,56,57,62}, // 7 8 9 2F , end-prog, esc, esc
{61,48,46,60} // En 0 . del, Xeq
};
//---------------------------------------------------------------
// pin assegnati al tastierino
//---------------------------------------------------------------
byte pinrighe[righe] = {4,5,6,7};
byte pincolonne[colonne] = {0,1,2,3};
// inizializza keypad e lcd
Keypad keypad = Keypad (makeKeymap(chiave),pinrighe,pincolonne,righe,colonne);
LiquidCrystal_I2C lcd(0x3F,16,2);
//**********************************************
// ARRAY DEL PROGRAMMA
//**********************************************
byte programma[100];
int riga = 0;
int ultimariga = 100;
int riga90 = 0;// qui si memorizza la riga inizio LBL
int riga91 = 0;
int riga92 = 0;
int riga93 = 0;
int riga94 = 0;
int riga95 = 0;
//----------------------------------------------------
// ----- variabili stak sub
int rigasubA = 0;
int rigasubB = 0;
int rigasubC = 0;
int rigasubD = 0;
int rigasubE = 0;
int rigasubF = 0;
int rigasubG = 0;
int rigasub = 0;
int rigaturn = 0;
//----------------------------------------------------
int rigaloop = 0; // punto di partenza dopo eventuale setup
//------------------------
//*** registri catasta
float regx = 0.0;
float regy = 0.0;
float regz = 0.0;
float regt = 0.0;
float lastx = 0.0; // recupero del registro x
float regu = 0.0;
// registri speciali
float regxs = 0.0; // per visualizzare la parte decimale della notazione sci
int esponente = 0; // esponente nella scientifica
float visore = 0.0; // accumula i valori immessi
//****************************************************************************
// STRINGHE
//****************************************************************************
String stringaMenu0 = String(' ');
String stringaMenu1 = String(' ');
String stringaUtente = String(' ');
//***********************
// memorie utente
//***********************
// registri per cicli for
int inc1 = 0; int cont1 = 0;
int inc2 = 0; int cont2 = 0;
int inc3 = 0; int cont3 = 0;
int inc4 = 0; int cont4 = 0;
int inc5 = 0; int cont5 = 0;
int inc6 = 0; int cont6 = 0;
//----------------------------
//--------------------------
float mem1 = 0.0;
float mem2 = 0.0;
float mem3 = 0.0;
float mem4 = 0.0;
float mem5 = 0.0;
float mem6 = 0.0;
float mem7 = 0.0;
float mem8 = 0.0;
float mem9 = 0.0;
float mem10 = 0.0;
float mem11 = 0.0;
float mem12 = 0.0;
float mem13 = 0.0;
float mem14 = 0.0;
float mem15 = 0.0;
float mem16 = 0.0;
float mem17 = 0.0;
float mem18 = 0.0;
float mem19 = 0.0;
//***********************
void setup()
{
lcd.init(); // initialize the lcd
lcd.clear();
lcd.backlight();
lcd.setCursor(0,0);
//lcd.print("1234567890123456");
lcd.print("ArduinoQuadro 13");
lcd.setCursor(0,1);
//lcd.print("1234567890123456");
lcd.print("Dicembre 2017 ");
delay (2000);
}
//**************************************************************
//**************************************************************
void loop()
{
inizializzazione(); // inizializzazione
iniarduino();
// scelte iniziali calcolatrice o arduQuadro menu
arduino();
while(arduQuadro == true)
{
nuovoprog(); // scelta se NEW (scrivere nuovo programma )
//oppure OLD programma in RAM
// finito la registrazione
// del programma o il caricamento da RAM
controllo(); // Si esegue il controllo e correzione
costanti();// Possiamo inserire dati nei registri
stringhe(); // per inseimento stringhe (da fare)
// pronto e si mette in attesa pressione tasto
pronto();
tasto();
// Esegue il programma utente
progUtente();
// uscita dal programma utente
fineprog();
}
// esegue come calcolatrice diretta
if (calcRPN == true) {uscitacalc = false;calcolatrice();}
}
//**** END LOOP ******************************************************
//********************************************************************
//******************************************
//******************************************
//** F U N Z I O N I **
//******************************************
//********************************************************************
void calcolatrice() // questa è un loop per utilizzare come calcolatrice
// manuale. Per uscire (uscitacalc = true;)
{
while (uscitacalc == false)
{
aggiornadisplay(); // sub che aggiona il display
tasto(); // attende pressione tasto
//-------------------------------------------------------------
// ****** si controlla lo stato della calcolatrice
// che può essere funzioni dirette o seconde funzioni 2F
if (stato == true)
{ // siamo in 2F )
funzioni_seconde();
}
if (stato == false)
{// siamo nelle funzioni dirette
funzioni_dirette();
}
}
calcRPN = false; // uscita da calcolatrice manuale
}
//***************** fine calcolatrice ******************************
// con queste si eseguono i comandi diretti da tastiera
void funzioni_dirette()
{
if (pdec == 0) // si deve scegliere fra numeri e numeri decimali
{
if ((codice >= 48) && (codice <= 57 ))
{impostanumero();}
}
if (pdec == 1) // è stato premuto il punto decimali
{
if ((codice >= 48) && (codice <= 57 ))
{impostanumerodec();}
}
// il codice è relativo ad una funzione oppure è stato attivato il tasto 2F
// per attivare le seconde funzioni
//seleziona la funzione la invia alla sub che la esegue e quindi ritorna
//
if (codice == 43)// somma
{somma();}
if (codice == 45) //sottrazione
{sottrazione();}
if (codice == 46) // punto decimali
{punto();} // con questa si pone a 1 la pdec
if (codice == 60)//cancella carattere
{del(); }
if (codice == 61)// ENTER
{enter();}
if (codice == 62) //seconda funzione 2f
{ stato = true;} // cambia stato
{}
return;
}
// ---- queste attivano le funzioni seconde della tastiera 2F (shift)
// vengono eseguite con la pressione del tasto 2F (shift) seguito dalla
// pressione del tasto relativo
//********* SE VIENE PREMUTO 2F (SHIFT) SI ESCE DA CALCOLATRICE MANUALE
//********** IN QUESTO CASO SI PASSA AL MENU' INIZIALE ARDU-QUADRO
void funzioni_seconde()
{
stato = false; // rimette false per tornare alle funzioni dirette
int codiceF2 = codice + 27;
//esegue una della funzioni F2 seconde
if (codiceF2 == 89)
{uscitacalc = true;}// uscita calcolatrice MANUALE
if (codiceF2 == 70)// moltiplicazione
{moltiplicazione();}
if (codiceF2 == 72) //divisione
{divisione();}
if (codiceF2 == 87) // Xeq esegue funzione da 1 a ...
{Xeq_nn();} // questa esegue una delle funzioni richiamabili
if (codiceF2 == 88)//Lastx ( recupera x )
{last_x(); }
if (codiceF2 == 75)// x<>y scambio x con y
{scambio();}
if (codiceF2 == 73) // R! scorre catasta
{ ruota(); }
if (codiceF2 == 81) //cambia segno (moltiplica x per -1)
{cambiasegno();}
if (codiceF2 == 76) // seno di x angolo in RADIANTI
{lastx = regx; regx = sin (regx);}
if (codiceF2 == 77)//tangente x angolo in x in RADIANTI
{ lastx = regx; regx = tan (regx);}
if (codiceF2 == 78)// coseno x angolo in x in RADIANTI
{ lastx = regx; regx = cos (regx);}
if (codiceF2 == 79) //radice quadrata
{ lastx = regx; regx = sqrt (regx);}
if (codiceF2 == 80)
// potenza eleva y alla x
//pow(base, exponent)
//base: numero (tipo float)
//exponent: la potenza a cui è elevata la base (tipo float)
// si utilizza x ed y della catasta
{ lastx = regx; regx = pow (regy, regx); }
if (codiceF2 == 84)//fix decimali
{visfix(); }
if (codiceF2 == 82)// STO n
{sto_n();}
if (codiceF2 == 83) //RCL n
{rcl_n(); }
codice = 0;
visore = 0;
return;
}
//*********************************************************************
//******** ARDUINO QUADRO *********************************************
//*********************************************************************
void inizializzazione()
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Inizializzazione");
delay (500);
//*******************************************************
stringaMenu0 = String(" ");
stringaMenu1 = String(" ");
//*******************************************************
old = false; // per segnalare programma già in memoria risposta no
si = true; // risposta si nelle scelte
gira = false; // se gira il programma va a true
arduQuadro = false;
calcRPN = false;
}
//****************************************************************
void iniarduino()
{
stringaMenu0 = String(" ");
stringaMenu1 = String(" ");
// registri per cicli for
inc1 = 0; cont1 = 0;
inc2 = 0; cont2 = 0;
inc3 = 0; cont3 = 0;
inc4 = 0; cont4 = 0;
inc5 = 0; cont5 = 0;
inc6 = 0; cont6 = 0;
//-------------------------------
rigasubA = 0;
rigasubB = 0;
rigasubC = 0;
rigasubD = 0;
rigasubE = 0;
rigasubF = 0;
rigasubG = 0;
rigasub = 0;
rigaturn = 0;
//------------------------------
riga = 0;
ultimariga = 100;
riga90 = 0;// qui si memorizza la riga inizio LBL
riga91 = 0;
riga92 = 0;
riga93 = 0;
riga94 = 0;
riga95 = 0;
//-------------------
//---------------------------------------------------
rigaloop = 0;
//----------------------------------------------------
looProg = false; // se true esegue loop
se = true; // per le funzion if
xeq = true; // per inserimento codice
dati = true; // si inseriscono i dati in costanti
prog = true; // si predispone per la programmazione
sub = true; // per eseguire le subroutin
endProg = false; // fine sub o programma
stopProg = false; // per fermare il loop
//--------------------------------------------------------------------
old = false; // per segnalare programma già in memoria risposta no
si = true; // risposta si nelle scelte
gira = false; // se gira il programma va a true
//--------------------------------------------------------------------
}
// con questa si sceglie se usare come
// calcolatrice RPN oppure come arduinoQuadro
//
void arduino()
{
//stringaMenu0 = String("1234567890123456");
stringaMenu0 = String("arduinoQuadro-13");
stringaMenu1 = String("1=CALC 3= arduQ ");
sceltemenu();
if (old == true){arduQuadro = true; calcRPN = false;} // si programma come arduQuadro
else {arduQuadro = false; calcRPN = true;}/// si usa come calcolatrice
}
void fineprog()
{
stringaMenu0 = String("Fine programma");
stringaMenu1 = String("1=STOP 3=CONT"); // si stop
sceltemenu();
if (si == true) {calcRPN = true; arduQuadro = false;}
}
// con questa si esegue un programma esistente
// si corregge un programma esistente
// oppure si sceglie di scriverne uno nuovo
void nuovoprog()
{
stringaMenu0 = String("Menu programma ");
stringaMenu1 = String("1=NEW - 3=OLD");
sceltemenu();
if (old == true){leggiprog();} // con old a true si legge il programma dalla EPROM
if (old == false) {scritturaprog();} // con old false si scrive nuovo programma
}
void sceltemenu()
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(stringaMenu0);
lcd.setCursor(0,1);
lcd.print(stringaMenu1);
boolean menu = true;
old = false; // tasto 3 risposta no
si = false; // tasto 1 risposta si
while (menu == true)
{
tasto();
if (codice == 49){si = true; menu = false;} // SI
if (codice == 51){old = true; menu = false; } // NO
}
}
//-------------------------------------------------------
void pronto()
{lcd.clear();
lcd.setCursor(0,1);
lcd.print("Premi un tasto ");
}
//*********************************************************************
//*********************************************************************
void tasto()
{
key = 0; // azzera variabile tasto del tasterino e
//************* attende la pressione di un tasto sul tastierino
while (key == 0) // rimane qui fino alla pressione di un tasto
{
key = keypad.getKey();
codice = key;
}
}
//*********************************************************************
void stringhe()// per inseimento stringhe (da fare)
{
stringaMenu0 = String("Stringhe ? ");
stringaMenu1 = String("1= SI - 3= NO");
sceltemenu();
if (old == true){return;} // non si inseriscono stringhe
// qui da fare inserimento stringhe
inseralfa();
}
//******************* EDITOR SCRITTURA PROGRAMMI UTENTE ******************
void scritturaprog()
// questa scrive e memorizza il programma UTENTE
{
// cancellazione programma in memoria
for (int i = 0; i < 100; i++)
{codProg = 0;
EEPROM.write(i, codProg);
}
//-------------------------------------
while ( prog == true)
{
inidisplay(); // editor scrittura codici
editor();
prog = false;
}
}
//********************************************************************
void inidisplay()
{
//INIZIALIZZAZIONE EDITOR
lcd.init();
lcd.clear();
lcd.backlight();
lcd.setCursor(0,0);
lcd.print("ARDUINO EDITOR");
lcd.setCursor(0,1);
lcd.print("Inserire codice");
delay (2000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("C>: ");
}
//********************************************************************
void editor() // QUI SI SCRIVONO I CODICI PROGRAMMA UTENTE
{
riga = 0;
int i=0;
while ( i<100)
{
impostacodice();
programma[i] = codProg;
riga = i;
i = i+1;
if (codice == 62)
{
ultimariga = i;
// programma[i] = 99;//ultimariga
i = 100;
}
editordisplay();
}
}
//***************************************************************************
// F I N E SCRITTURA PROGRAMMA
//***************************************************************************
// CON QUESTA SI RIVEDE IL PROGRAMMA
//e consente la correzione di passi di programma
void controllo()
{
prelabora();
stringaMenu0 = String("Controllo ? ");
stringaMenu1 = String("1= SI - 3= NO");
sceltemenu();
if (old == true){return;} // non esegue il controllo
// esegue il controllo
lcd.clear();
lcd.setCursor(0,0);
//ultimariga = riga;
int c = 0;
while (c<ultimariga)
{
codProg = programma[c];
riga = c;
editordisplay();
lcd.setCursor(0,1);
// lcd.print("1234567890123456");
lcd.print("cont> end> corr>");
tasto();
if (codice == 45) // correzione linea TASTO (-)
{
// scrivere la correzione
// questo tipo di correzione sostituisce
// la riga errata con altra corretta
// lasciando invatiato il resto del programma
//** PER CANCELLARE INTRODURRE UNA NOP **** codice 49
// la NOP non farà nulla e non altera il programma
// ma occorre tener conto delle istruzioni precedenti o
// seguenti che potrebbero utilizzare le informazioni
// della riga cancellata (if, rcl, sto, pin ...)
impostacodice();
programma[c] = codProg;
c = c-1; // per rivedere la correzione effettuata
lcd.setCursor(0,1);
// lcd.print("1234567890123456");
lcd.print("correzione OK ");
delay (300);
}
if (codice == 43) // inserimento linea TASTO (+)
{
// si preme + (43) sul numero riga che si vuole inserire
// ci chiede d'impostare il nuovo codice da inserire
// quindi sposta tutte le linee aggiungento una riga
int ins = c; // numero linea da inserire
lcd.setCursor(0,1);
// lcd.print("1234567890123456");
lcd.print("ins new codice ");
delay (300);
impostacodice();
int newCodice = codProg;
// aggiunge un posto all'array
ultimariga = ultimariga +1;
int i = ultimariga;
// ciclo che parte dal fondo e sposta tutte le linee
// fino alla riga da inserire
while ( ins < i )
{
programma[i] = programma[ i -1];
i = i-1;
}
// ora inserisce il nuovo codice al suo posto
programma[ins] = newCodice;
// conferma correzione
c = ins-1;
lcd.setCursor(0,1);
lcd.print("correzione OK ");
delay (300);
}
// tasti funzione
if (codice == 62){ c = ultimariga;} // esce dal controllo
if (codice == 49) { c = c+1;}// avanti (1)
if (codice == 51) {c = c-1;} // indietro (3)
}
salvaprog();
// se vogliamo possiamo salvarlo nella EEPROM
}
//***************************************************************
void salvaprog() // si scrive il programma in memoria
{
stringaMenu0 = String("Salva in RAM ");
stringaMenu1 = String("1= SI - 3= NO");
sceltemenu();
if (old == true){return;}
if (old == false)
{
for (int i = 0; i < ultimariga; i++)
{codProg = programma[i];
EEPROM.write(i, codProg);
}
lcd.setCursor(0,1);
// lcd.print("1234567890123456");
lcd.print("Salvataggio OK ");
delay (300);
}
}
void leggiprog() // qui il codice per leggere il programma in memoria
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Legge prog da RAM");
for (int i = 0; i < 100; i++)
{ codProg = EEPROM.read(i);
programma[i] = codProg;
}
prelabora(); // predispone il programma letto da ram
}
//****************************************************************
void editordisplay()
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print("n: ");
lcd.setCursor(4,0);
lcd.print (riga);
lcd.setCursor(10,0);
lcd.print (codProg);
if (codice == 62)
{
lcd.setCursor(0,1);
lcd.print("fine programma");
delay (3000);
}
}
//*********************************************
void aggiornadisplay()
{
//***************
// mostra display
//---------------
// si esegue il controllo se visualizzare in notazione sci o con fix
double testx = regx;
if (testx < 0) testx = testx*-1;
if (testx > k1) sciee = true;
if (testx < k0) sciee = true;
if (testx == 0) sciee = false;
lcd.clear();
lcd.setCursor(0,0);
lcd.print("X:");
lcd.setCursor(4,0);
if (sciee == true)
{
sci(); // sub per notazione scientifica
lcd.print(regxs,5);
lcd.setCursor(14,0);
lcd.print (esponente);
}
else lcd.print(regx,fix); // visualizzazione normale
lcd.setCursor(0,1);
if (stato == false){lcd.print("1:");}
if (stato == true) {lcd.print("2:");}
lcd.setCursor(4,1);
lcd.print(visore,fix);
sciee = false;
}
// questa sub prepara "regxs" ed "esponente" per visualizzare in notazione sci
// ATTENZIONE regxs serve solo per la visualizzazione di numeri in notazione
// scientifica in abbinamento al registro "esponente"
// non coinvolgere direttamente nei calcoli i due rappresentano comunque
// il contenuto di "regx" che deve essere utilizzato per il calcolo.
void sci()
{
lastx = regx;
double numero = regx;
int segno = 1;
int segnoe = 1;
esponente = 0;
// se il numero è negativo si trasforma in positivo
// ma si mette a -1 la variabile segno, ci servirà
// per ritornare a negativo dopo aver trovato
// il valore dell'esponte con la log10(numero)
if (numero < 0) {numero = numero *-1; segno = -1;}
double numlog = log10(numero); // si ottiene il logaritmo del numero
// N,xxxxx preleveremo la parte
// intera che rappresenta l'esponente
esponente = int( numlog); // adesso abbiamo il numero intero esponente
numero = numero*segno; // si ripristina il giusto segno
// si esegue il controllo se l'esponente è negativo e si
//esegue la stessa procedura fatta per il numero
if (esponente <0){esponente = esponente *-1; segnoe = -1;}
//-----------------------------------------------------------------------
// se segnoe è negativo il numero è molto piccolo
if (segnoe == -1){regxs = numero * pow(10,esponente);}
else regxs = numero / pow(10,esponente); //altrimenti numero molto grande
//------------------------------------------------------------------------
esponente = esponente * segnoe; // si ripristina il giusto segno
// all'esponente
}
//*********************************************************
// con questa si inseriscono dati nei registri
//*********************************************************
void insertdati()
{
if (pdec == 0) // si deve scegliere fra numeri e numeri decimali
{
if ((codice >= 48) && (codice <= 57 ))
{impostanumero();}
}
if (pdec == 1) // è stato premuto il punto decimali
{
if ((codice >= 48) && (codice <= 57 ))
{impostanumerodec();}
}
if (codice == 43)// sto-n memorizza x nel reg indicato da visore
{indirizzo = visore; sto_n(); lcd.print(" ok "); delay (300);}
if (codice == 45) // inserire in X numero da raggiungere,
// attenzione si usano interi 32767 -32768
{gira = false; indirizzo = visore; inc_n();lcd.print(" ok "); delay (300);}
if (codice == 46) // punto decimali
{punto();} // con questa si pone a 1 la pdec
if (codice == 60)//cancella carattere
{del(); }
if (codice == 61)// ENTER
{enter();}
if (codice == 62) //fine dati
{ }
return;
}
void inseralfa()
{
lcd.clear();
lcd.setCursor(0,0);
stringaUtente = ("");
while (codice != 62)
{
impostacodice();
char codAlfa = codProg;
String stringa0 = String(codAlfa);
stringaUtente = String(stringaUtente + stringa0);
lcd.clear();
lcd.setCursor(0,0);
lcd.print(stringaUtente);
}
alfadisplay();
}
void alfadisplay()
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(stringaUtente);
if (codice == 62)
{
lcd.setCursor(0,1);
lcd.print("string ok ");
delay (2000);
}
}
void costanti()
{
stringaMenu0 = String("Ins. Dati ? ");
stringaMenu1 = String("1= SI - 3= NO");
sceltemenu();
if (old == true){return;} // salta inserimento dati
// inseimento dati valori
dati = true;
while ( dati == true)
{
aggiornadisplay(); // sub che aggiona il display
tasto();
insertdati();
if (codice == 62){dati = false;}
}
lcd.clear();
lcd.setCursor(0,0);
lcd.print("OK dati inseriti");
delay (1000);
}
//***********************************************************************
// INTERPETRA ED ELABORA IL PROGRAMMA UTENTE
//***********************************************************************
void prelabora()
{
//*********** PRE ELABORAZIONE *************************************
// questa parte legge tutto il programma e cerca le LBL (90,91,92,93,94,95)
// cerca anche se esiste l'istruzione loop (47) in questo caso
// pone a true la looProg ed il programma UTENTE continurà a girare
// fino ad un reset esterno.
looProg = false;
rigaloop = 0;
for (int c = 0; c<ultimariga; c++) // prepara programma
{codProg = programma[c];
if ( codProg == 90){riga90 = c;} // memorizza inizio LBL
if ( codProg == 91){riga91 = c;}
if ( codProg == 92){riga92 = c;}
if ( codProg == 93){riga93 = c;}
if ( codProg == 94){riga94 = c;}
if ( codProg == 95){riga95 = c;}
if ( codProg == 47){looProg = true; rigaloop = c;}// quando trova end riparte da rigaloop
//if ( codProg == 99){ultimariga = c;}// memorizza l'ultima riga
}
}
//**************************************************************************
void progUtente()
{
gira = true;
prelabora();
//*************************************************************************
//*************************** elaborazione programma **********************
//*************************************************************************
if (looProg == true)
{
int cloop = rigaloop;
rigaloop = 0;
cicloprogramma(); // esegue la prima volta il programma da zero
rigaloop = cloop;
}
if (looProg == true)
{
while (looProg == true)
cicloprogramma(); // ora il programma gira sempre
// interrupt
// con pulsante
// che ferma il loop
// mettendo looProg a false
}
else {cicloprogramma();}
gira = false; // fine programma
while(codice == 62)
{
aggiornadisplay(); // sub che aggiona il display
tasto();
}
}
//**************************************************************************
void cicloprogramma()
{
int c = rigaloop;
rigasub = 0;
codProg = 0;
while (codProg != 46) // quando END esce
{
codProg = programma[c];
riga = c;
se = false;
//----------------------------------------------------
if ( codProg == 80){ rigasub = c; staksub(); c = riga90;}
if ( codProg == 81){ rigasub = c; staksub(); c = riga91;}
if ( codProg == 82){ rigasub = c; staksub(); c = riga92;}
if ( codProg == 83){ rigasub = c; staksub(); c = riga93;}
if ( codProg == 84){ rigasub = c; staksub(); c = riga94;}
if ( codProg == 85){ rigasub = c; staksub(); c = riga95;}
//-----------------------------------------
if (codProg == 48){ stak(); c = rigaturn;}
eseguiprog();
if (se == true) { c = c+1;}
// se una if è vera torna true
// e quindi si salta la riga successiva
// altrimenti il prog continua normale
c = c+1;
}
}
//*********************************************************
// ---- pila per le sub ----------
void staksub() // fa salire in catasta stak delle sub il valore in rigasub
{
rigasubG = rigasubF;
rigasubF = rigasubE;
rigasubE = rigasubD;
rigasubD = rigasubC;
rigasubC = rigasubB;
rigasubB = rigasubA;
rigasubA = rigasub;
}
void stak () // FA SCENDERE LO STAK E RESTITUISCE LA RIGA SUB
{
rigaturn = rigasubA;
rigasubA = rigasubB;
rigasubB = rigasubC;
rigasubC = rigasubD;
rigasubD = rigasubE;
rigasubE = rigasubF;
rigasubF = rigasubG;
}
//******************************************
void eseguiprog()
{
// esegue le funzioni
funzioni();
aggiornadisplay();
}
// ************************************************************************
//*************************************************************************
//************************************************
// queste sono FUNZIONI chiamate dal programma
//***********************************************
// si distinguono dal "codice" che in questo caso diventa "codProg"
void funzioni() // ESEGUIBILI DA PROGRAMMA UTENTE
{
// ------------------------------------------------
if (( codProg >= 0) && ( codProg < 20))
{ indirizzo = codProg; visore = codProg;}
// i numeri compresi da 0 a 19
// sono indirizzi per le funzioni che li
// richiedono stoxnn, rclxnn, pin ....
//-------------------------------------------------
// **** per la PRINT da programma
if ( codProg == 20) // pulisce il display e scrive la stringa utente
// attende la pressione di un tasto per continuare
// visualizza registro x
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print("X:");
lcd.setCursor(4,0);
lcd.print(regx);
lcd.setCursor(0,1);
lcd.print(stringaUtente);
tasto();
}
// *** per effettuare input da programma
if (codProg == 21) { costanti(); } // inserimento dati
//-------------------------------------------------
// *** ARDUINO *****
if (codProg == 30) // pin nn input
{ pinMode ( indirizzo, INPUT);}
if (codProg == 31) // pin nn output
{ pinMode ( indirizzo, OUTPUT);}
if (codProg == 32) //--pin nn HIGH
{ digitalWrite( indirizzo, HIGH); }
if (codProg == 33) //--pin nn LOW
{ digitalWrite( indirizzo, LOW); }
if (codProg == 34)//-- legge il pin e inserisce il valore in x
{regx = digitalRead (indirizzo );}
if (codProg == 35) //-- legge il pin ed inserisce il valore in x
{
int pin = 0;
if (indirizzo == 0) {pin = A0;}
if (indirizzo == 1) {pin = A1;}
if (indirizzo == 2) {pin = A2;}
if (indirizzo == 3) {pin = A3;}
regx = analogRead(pin);}
if (codProg == 36) // disponibile
{ analogWrite (indirizzo, regx); }
if (codProg == 37) // delay
{ delay_mm(); } // in visore codice da 01 a 06
//1 = 5 mms, 2= 10, 3= 50, 4= 250, 5=500, 6 = 1000 mms
if (codProg == 38) // TONE (PIN,FREQUENZA,DURATA)
// in indirizzo il pin nel regx la frequenza
// in y porre zero ( per fermare occorre la NOTONE)
// oppure inserire in y la durata
{ if (regy == 0){ tone(indirizzo, regx);}
else {tone(indirizzo,regx, regy);}
}
if (codProg == 39) //
{ noTone( indirizzo); }
//-----------------------------------------------------
// **** CONTROLLO ******
if (codProg == 40) //---controlla se x > di y
{if ( regx > regy ){se = true;}}
if (codProg == 41) //--- controlla se x < di y
{if (regx < regy) {se = true;}}
if (codProg == 42) //---controlla se x = y
{if (regx == regy){se = true;}}
if (codProg == 43) //----controlla se x è > di 0
{ if ( regx > 0){se = true;}}
if (codProg == 44)//--- controlla se x è < di 0
{ if ( regx < 0){se = true;}}
if (codProg == 45)//
{inc_n(); }
// ---- codici particolari ---------------------------------------
if (codProg == 46) // END FINE PROGRAMMA UTENTE
{}// da inserire prima di eventuali sub
// esegue uscita dal programma
// se esiste l'istruzione loop
// rimanda alla rigaloop
if (codProg == 47)// LOOP programma
{} // memorizza la riga inizio loop
// del programma che puo essere diversa
// dalla 0
if (codProg == 48)// RTN ritorno dalle sub
{}
if (codProg == 49)//
{} // NOP non fa nulla
//--------------------------------------------------------------------
// ****** MATEMATICHE *****
if (codProg == 50) //sottrazione
{sottrazione();}
if (codProg == 51) // moltiplicazione
{moltiplicazione();}
if (codProg == 52) // divisione
{divisione();}
if (codProg == 53)// somma
{somma();}
if (codProg== 54) //cambia segno (moltiplica x per -1)
{cambiasegno();}
if (codProg == 55) // potenza eleva y alla x
{ lastx = regx; regx = pow (regy, regx); }
//pow(base, exponent)
//base: numero (tipo float)
//exponent: la potenza a cui è elevata la base (tipo float)
// si utilizza x ed y della catasta
if (codProg == 56) // 1/x
{unosux();}
if (codProg == 57) // intero di x
{}// {interox();}// da fare
if (codProg == 58) // radice di x
{ lastx = regx; regx = sqrt (regx);}
if (codProg == 59)// disponibile
{ }
//----------------------------------------------------------
// ***** CATASTA OPERATIVA *****
if (codProg == 60)// cancella
{del();}
if (codProg == 61)// ENTER
{enter();}
if (codProg == 62)// cancella registri e catasta
{ cancella();} //CLST
if (codProg == 63) //Lastx ( recupera x )
{last_x(); }
if (codProg == 64)// x<>y scambio x con y
{scambio();}
if (codProg == 65) // abbassa catasta R!
{ ruota();}
if (codProg == 66)// cancella registo x
{lastx = regx; regx = 0.0;}
if (codProg == 67)// memorizza x nel nn indicato nel precedente codice
{sto_n();}
if (codProg == 68)// richiama in x nn indicato nel precedente codice
{rcl_n();}
if (codProg == 69)// ruota su catasta
{ ruotaSU(); }
//----------------------------------------------------------
// **** TRIGONOMETRICHE ANGOLO IN RADIANTI *****
if (codProg == 70) // PI GRECO
{ lastx = regx; regx = PI;}// richiama pigreco
if (codProg == 71) // seno di x angolo in RADIANTI
{lastx = regx; regx = sin (regx);}
if (codProg == 72)// coseno x angolo in x in RADIANTI
{ lastx = regx; regx = cos (regx);}
if (codProg == 73)//tangente x angolo in x in RADIANTI
{ lastx = regx; regx = tan (regx);}
if (codProg == 74)// arco seno di x
{arcosen_x();}
if (codProg == 75)// arco coseno di x
{arcocos_x();}
if (codProg == 76)// arco tangente di x
{arcotan_x();}
//---------------------------------------------------------------
// **** FUNZIONI PER FLUSSO SUB GOTO *****
// la 88 Xeq_nn richiama altre funzioni aggiuntive
if (codProg == 80)
{ }// chiamata sub0 (90)
if (codProg == 81)
{ } // chiamata sub1 (91)
if (codProg == 82)
{ } // chiamata sub2 (92)
if (codProg == 83) // // chiamata sub3 (93)
{ }
if (codProg == 84) // // chiamata sub4 (94)
{ }
if (codProg == 85) // // chiamata sub5 (95)
{ }
if (codProg == 86) // disp
{ }
if (codProg == 87) // disp
{ }
if (codProg == 88) // esegue la funzione nn da 1 a nn
{ Xeq_nn();}
// alle funzioni scritte se ne possono aggiungere
// altre.
if (codProg == 89) // disp
{ }
//---------------------------------------------------------------
// **** funzioni flusso LABEL DELLE SUB E DEL GOTO *****
// LA 99 END-END chiude il programma
if (codProg == 90)
{ }// label LBL0
if (codProg == 91) // label
{}
if (codProg == 92)// label
{ }
if (codProg == 93) // label
{ }
if (codProg == 94) // label
{}
if (codProg == 95) // label
{ }
if (codProg == 96) // DISP
{}
if (codProg == 97) // DISP
{ }
if (codProg == 98) // DISP
{}
if (codProg == 99) // end-end
{codProg = 46; } // end
//----------------------------------------------------------------
return;
}// fine chiamata funzioni di programma utente
//****************************************************************
//****************************************************************
//****************************************************
// ESEGUE LE FUNZIONI CHIAMATE
//****************************************************
//****************************************************************
// parte intera di un numero si scrive su visore
void impostacodice()
{
xeq = true;
while(xeq == true)
{
byte cifra = 0;
byte cifra2 = 0;
tasto();
if (codice == 62){xeq = false;}
if ((codice >= 48) && (codice <= 57 ))
{
cifra = codice - 48;
}
tasto();
if (codice == 62){xeq = false;}
if ((codice >= 48) && (codice <= 57 ))
{
cifra2 = codice - 48;
codProg = cifra*10 + cifra2;
if ((codProg >= 0 )&& (codProg < 100))
{xeq = false;}
}
if (codice == 43){}
if (codice == 45){}
if (codice == 46){}
if (codice == 60){}
if (codice == 61){}
}
}
//---------------------------------------------------------------
void impostanumero()
{
poscifra = poscifra +1;
if (poscifra < 9)
{int cifra = codice - 48;
visore = visore * 10 + cifra;
}
else { codice = 61;}
}
//****************************************************************
// si scrive su visore il numero decimale
void impostanumerodec()
{
ndec = ndec+1;
if (fix >= ndec)
{
float cifradec = (codice - 48.0);
if (ndec == 1) {visore = visore + (cifradec /10);}
if (ndec == 2){visore = visore + (cifradec /100);}
if (ndec == 3){visore = visore + (cifradec /1000);}
if (ndec == 4){visore = visore + (cifradec /10000);}
if (ndec == 5){visore = visore + (cifradec /100000);}
}
else { codice = 61;}
}
//----------------------------------------------------------
//***************************************************************
void unosux() //
{
if (regx == 0)return;
regx = ( 1 /regx);
}
void somma()//
{
// somma il contenuto di x con y
// ricorda in lastx e last y i due valori
// azzera la y in x abbiamo il risultato
lastx = regx;
regx = (regx + regy);
regy = regz;
regz = regt;
regt = regu;
del();
}
void sottrazione()//
{
// sottrae x da y
lastx = regx;
regx = (regy - regx);
regy = regz;
regz = regt;
regt = regu;
del();
}
// punto decimali
void punto()
{
pdec = 1;
ndec = 0;
codice =0;
}
//cancella carattere
void del() //60
{
visore = 0;
poscifra =0;
codice = 0;
pdec = 0;
ndec = 0;
}
//61 da codice
void enter()
{
regu = regt;
regt = regz;
regz = regy;
regy = regx;
regx = visore;
//lastx = regx;
// prima sale la catasta
// poi azzera
del();
}
// moltiplicazione //
void moltiplicazione()
{
lastx = regx;
regx = (regy * regx); // esegue la moltiplicazione
regy = regz;
regz = regt;
regt = regu;
del();
}
//divisione //
void divisione()
{
if (regx == 0) return; //******* divisione per 0
lastx = regx; // prima salva in lastx il valore di x
regx = (regy / regx); // esegue la divisione
regy = regz;
regz = regt;
regt = regu;
del();
}
// clr // CLST
void cancella() //cancella catasta e visore
{
regu = 0.0;
regt = 0.0;
regz = 0.0;
regy = 0.0;
regx = 0.0;
lastx = 0.0;
visore = 0.0;
poscifra =0;
codice = 0;
pdec = 0;
ndec = 0;
}
void cancella_mem()// cancella memorie utente
{
mem1 = 0.0;
mem2 = 0.0;
mem3 = 0.0;
mem4 = 0.0;
mem5 = 0.0;
mem6 = 0.0;
mem7 = 0.0;
mem8 = 0.0;
mem9 = 0.0;
mem10 = 0.0;
mem11 = 0.0;
mem12 = 0.0;
mem13 = 0.0;
mem14 = 0.0;
mem15 = 0.0;
mem16 = 0.0;
mem17 = 0.0;
mem18 = 0.0;
mem19 = 0.0;
}
//Lastx
void last_x()
{
regu = regt;
regt = regz;
regz = regy;
regy = regx;
regx = lastx;
}
// x<>y scambio
void scambio()
{
float scambio = regx;
regx = regy;
regy = scambio;
}
//ruota giu la catasta
void ruota()
{
float ruota = regx;
regx = regy;
regy = regz;
regz = regt;
regt = regu;
regu = ruota;
}
//ruota SU la catasta
void ruotaSU()
{
float ruota = regu;
regu = regt;
regt = regz;
regz = regy;
regy = regx;
regx = ruota;
}
//cambiosegno
void cambiasegno()
{
lastx = regx; regx = regx * -1;
}
// FIX----- scelta numero decimali dopo il punto da 0 a 5
void visfix()
{ if (( visore < 0 )|| (visore > 5)) return;
else fix = visore;
}
void arcosen_x() // funzione XEQ 1 ritorna angolo in x in RADIANTI
{ if ((regx < -1)||( regx > 1)) return;
{lastx = regx; regx = asin (regx);}
}
void arcocos_x() // funzione XEQ 3 ritorna angolo in x in RADIANTI
{ if ((regx < -1)|| ( regx > 1)) return;
{lastx = regx; regx = acos (regx);}
}
void arcotan_x() // funzione XEQ 2 ritorna angolo in x in RADIANTI
{lastx = regx; regx= atan (regx);}
// converte x da sessagesimale a sessadecimale
// solo il registro x della catasta viene utilizzato
void sess_sedec() // FUNZIONE
{
lastx = regx;
float a = regx;
int b = int(a); // i gradi
float c = (a-b)*100;
int d = int(c);
float pri = d/60.0; // primi
float sec = (c-d)/36.0; // i secondi
regx= (b+pri+sec);
}
// converte x da sessadecimali a sessagesimali
// solo il registro x della catasta viene utilizzato
void sedec_sessa() // FUNZIONE XEQ 5
{
lastx = regx;
float a = regx;
int b = int(a); // i gradi
float c = (a-b)*60;
int d = int(c); // i primi
float pri = d/100.0;
float sec = (c-d)*6/1000.0; // i secondi
regx= (b+pri+sec);
}
// da polari a rettangolari inserire in x l'angolo alfa
// in gradi RADIANTI
// inserire in y la magnitudine
// restituisce le cordinate in x e y
void P_R()
{
double magni = regy;
double alfa = (regx);
if (magni < 0)return;
if (alfa > (2*PI))return;
if (alfa < 0 )return;
regx = magni*cos(alfa);
regy = magni*sin(alfa);
}
// da rettangolari a polari insere in x la coordinata x ed in y la cooordinata y
// restituisce in y la distanza
// e restituisce in x angolo in RADIANTI
//
void R_P()
{
double alfa = 0;
double magni = sqrt((regx*regx)+ (regy*regy));
alfa = atan2(regy,regx);
regx = alfa;
regy = magni;
}
// questa sub serve ad inserire un numero molto grande o molto piccolo
// in catasta inserendo in y il valore n.nnnnn ed in x l'esponente base 10
void inputsci()
{
double numero = regy;
double esp = regx;
regx = numero * pow(10,esp);
regxs = regx;
esponente = esp;
sciee = true;
}
void fact() // funzione 19 fattoriale *****
{
int numero = regx;
double fact = 1.0;
regx = fact;
if ((numero < 1)||(numero > 31)) return;
else {
for ( int i = numero; i > 1; i--)
{fact = fact * i;}
regx = fact;
}
} // end fact
//---------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
// STO n SUB PER MEMORIZZARE IL CONTENUTO DI X
//NEL REGISTRO INDICATO IN VISORE DA 1 A 19
// MA SE OCCORRE SI PUO' AUMENTARE LE MEMORIE UTENTE
// IN QUEL CASO OCCORRE VARIARE ANCHE LA SUB RCL
// E LA SUB CHE CANCELLA IL CONTENUTO MEMORIE UTENTE
// CIOE LA 12 cancella_mem
void sto_n()
{
int mem = visore;
if (( mem < 1 )||(mem > 19)) return;
switch (mem)
{
case 1:
mem1 = regx;
break;
case 2:
mem2 = regx;
break;
case 3:
mem3 = regx;
break;
case 4:
mem4 = regx;
break;
case 5:
mem5 = regx;
break;
case 6:
mem6 = regx;
break;
case 7:
mem7 = regx;
break;
case 8:
mem8 = regx;
break;
case 9:
mem9 = regx;
break;
case 10:
mem10 = regx;
break;
case 11:
mem11 = regx;
break;
case 12:
mem12 = regx;
break;
case 13:
mem13 = regx;
break;
case 14:
mem14 = regx;
break;
case 15:
mem15 = regx;
break;
case 16:
mem16 = regx;
break;
case 17:
mem17 = regx;
break;
case 18:
mem18 = regx;
break;
case 19:
mem19 = regx;
break;
}
visore = 0;
} // fine void sto_n
//-------------------------------------------------------------------------------------------------
//RCL richiama in x uno dei registri
void rcl_n()
{
indirizzo = visore;
int mem = indirizzo;
if (( mem < 1 )||(mem > 19)) return;
switch (mem)
{
case 1:
{ visore = mem1; enter();}
break;
case 2:
{visore = mem2; enter();}
break;
case 3:
{visore = mem3; enter();}
break;
case 4:
{visore = mem4; enter();}
break;
case 5:
{visore = mem5; enter();}
break;
case 6:
{visore = mem6; enter();}
break;
case 7:
{visore = mem7; enter();}
break;
case 8:
{visore = mem8; enter();}
break;
case 9:
{visore = mem9; enter();}
break;
case 10:
{visore = mem10; enter();}
break;
case 11:
{visore = mem11; enter();}
break;
case 12:
{visore = mem12; enter();}
break;
case 13:
{visore = mem13; enter();}
break;
case 14:
{visore = mem14; enter();}
break;
case 15:
{visore = mem15; enter();}
break;
case 16:
{visore = mem16; enter();}
break;
case 17:
{visore = mem17; enter();}
break;
case 18:
{visore = mem18; enter();}
break;
case 19:
{visore = mem19; enter();}
break;
}
}
//-------------------------------------------------------------------------------------------------
void Xeq_nn()
{ int mem = visore;
if (( mem < 1 )|| ( mem > 99)) return;
switch (mem)
{
case 1:
{arcosen_x();}// arcoseno di x in radianti
break;
case 2:
{arcotan_x();}// arcotangente ritorna angolo in x in RADIANTI
break;
case 3:
{arcocos_x();} // arco coseno di x in radianti
break;
case 4:
sess_sedec(); // converte da sessagesimali a sessadecimali
break;
case 5:
sedec_sessa(); // converte da sessadecimali a sessagesimali
break;
case 6:
{ lastx = regx; regx = PI;}// richiama pigreco
break;
case 7:
// converte da radianti in sessagesimali
{lastx = regx; regx = regx*180.0/PI; sedec_sessa();}
//Log10
// {lastx = regx; regx = log10(regx);}
break;
case 8:
// da gradi sessagesimali a radianti
{lastx = regx; sess_sedec();regx = regx*PI/180.0;}
break;
case 9:
// cancella registri e catasta
{ cancella();} //CLST
break;
case 10:
R_P (); // da rettangolari a polari
break;
case 11:
P_R(); // da polari a rettangolari p>=0 e alfa >=0 e <= pi/2
break;
case 12:
cancella_mem(); // cancella memerie utente
break;
case 13:
{ if (sciee == false) sciee = true;
else sciee = false;}
break;
case 14:
inputsci(); //EEX
break;
case 15:
// ln
{lastx = regx; regx = log(regx);}
break;
case 16:
// exp e^x
{lastx = regx; regx = exp(regx);}
break;
case 17:
//10alla x
{if (regx < 30)
{lastx = regx; regx = pow(10,regx);}}
break;
case 18:
// disponibile
break;
case 19:
// calcolo fattoriale di x max 30
fact();
break;
case 20:
// da radianti a centesimali
{ lastx = regx; regx = regx*200.0/PI;}
break;
case 21:
// da centesimali a radianti
{ lastx = regx; regx = regx*PI/200.0;}
break;
case 22:
// disponibile
break;
case 23:
// disponibile
break;
case 24:
// disponibile
break;
case 25:
// disponibile
break;
case 26:
// disponibile
break;
case 27:
// disponibile
break;
case 28:
// disponibile
break;
case 29:
// disponibile
break;
case 30:
// disponibile
break;
case 31:
// disponibile
break;
case 32:
// disponibile
break;
case 33:
// disponibile
break;
case 34:
// disponibile
break;
case 35:
// disponibile
break;
case 36:
// disponibile
break;
case 37:
// disponibile
break;
case 38:
// disponibile
break;
case 39:
// disponibile
break;
case 40:
// disponibile
break;
}
} // fine void XEQ
//**********************************************************************************************
//***********************************************************************************************
// ************ per simulare il for *************************************************************
// nella inc1, inc2 ... ecc viene inserito il valore target lo prende da x in fase inserimento
// lo step è fisso uguale ad 1
// la variabile cont viene azzerata in fase di inserimento
// **********
// nella fase di elaborazione con gira == true
// cont viene incrementato di 1 ad ogni passaggio
// il registro x viene salvato in lastx in regx viene posto il cont attuale
// nel registro regy viene posto inc (target)
// a questo punto si può effettuare un controllo x con y ed verificare se il target è raggiunto.
//***********************************************************************************************
void inc_n()
{
int mem = visore;
if (( mem < 1 )||(mem > 6)) return;
switch (mem)
{
case 1:
if (gira == false){inc1 = regx; cont1 = 0;} // nella fase inserimento
else { cont1 = cont1+1; lastx = regx; regx = cont1; regy = inc1; }
// nella fase elaborazione gira = true
break;
case 2:
if (gira == false){inc2 = regx; cont2 = 0;}
else { cont2 = cont2+1; lastx = regx; regx = cont2; regy = inc2; }
break;
case 3:
if (gira == false){inc3 = regx; cont3 = 0;}
else { cont3 = cont3+1; lastx = regx; regx = cont3; regy = inc3; }
break;
case 4:
if (gira == false){inc4 = regx; cont4 = 0;}
else { cont4 = cont4+1; lastx = regx; regx = cont4; regy = inc4; }
break;
case 5:
if (gira == false){inc5 = regx; cont5 = 0;}
else { cont5 = cont5+1; lastx = regx; regx = cont5; regy = inc5; }
break;
case 6:
if (gira == false){inc6 = regx; cont6 = 0;}
else { cont6 = cont6+1; lastx = regx; regx = cont6; regy = inc6; }
break;
}
} // fine void inc_n
//-------------------------------------------------------------------------
void delay_mm()
{
//int mem = visore;
int mem = indirizzo;
if (( mem < 1 )||(mem > 6)) return;
switch (mem)
{
case 1:
{ delay(5);}
break;
case 2:
{ delay(10);}
break;
case 3:
{ delay(50);}
break;
case 4:
{ delay(100);}
break;
{ delay(250);}
case 5:
{ delay(500);}
break;
case 6:
{ delay(1000);}
break;
}
} // fine
//*******************************************************************************
//********************************************************************************
// F I N E L I S T A T O **************************************************
//
//********************************************************************************
SERGIO & ADRIANO PRENLELOUP
23/12/2017
file= arduinoQuadro-14
--------------------------------------------------------------------------
Con questo sketch si realizza una calcolatrice programmabile, che potrà
fare calcoli diretti, programmi utente con funzioni matematiche e trigonometriche,
sono disponibili PIN DIGITALI E PIN ANALOGICI che possono essere utilizzati
per input output.
Si potrà scrivere un piccolo programma che potrà essere conservato in ram.
Una volta lanciata l'esecuzione il programma viene eseguito dall'interpetre.
E si potranno visualizzare risultati sul display LCD, immettere dati
dalla tastiera, e/o utilizzare i pin disponibili di Arduino.
In questo modo si realizza un "Arduino-arduino".
Queste le caratteristiche:
Programmazione diretta con la scrittura di piccoli programmi nel linguaggio
"Codice99".
Questo linguaggio appositamente preparato si basa su 99 codici che possono essere
scritti in ram e che successivamente l'interpetre utilizzerà per eseguire la relativa funzione.
Ad ogni codice corrisponde una funzione.
(Alcune funzioni avranno bisogno di più codici)
L'immissione del programma in ram avviene con un micro editor che consente
di scrivere il programma.
Rivederlo scorrendo le istruzioni e correggere errori.
Una volta scritto il programma potrà essere eseguito e/o salvato nella EEPROM
(salvandolo nella EEPROM rimane permanente fino alla cancellazione).
Questo arduino avrà alcuni registri speciali (catasta operativa)
X, Y, Z, T, U, lastX.
Ci saranno alcuni registri di memoria che i programmi utente potranno utilizzare.
//**********************************************************************************************************
FUNZIONI PROGAMMABILI E RELATIVI CODICI.
MEMORIE & INDICI = da 00 a 19 (questi codici vengono immessi prima della istruzione che li
utilizza. prima si imposta il numero e poi l'istruzione.
Es. prima 01 poi 67 (STOnn) in questo caso il contenuto di x viene
memorizzato nel regisro mem1
Le istruzioni qui sotto con (*) DEVONO ESSERE PRECEDUTE DALL'INDICE
------------------------------------------------------------------------------------------------------------
I/O = 20 PRINT 21 INPUT da 22 a 29 disponibili
------------------------------------------------------------------------------------------------------------
ARDUINO = 30 *PINPUT 31 *PIOUT 32 *DWHIGH 33 *DWLOW 34 *DREAD 35 *AREAD 36 *AWRITE
37 *DELAYn 38 *TONE 39 *NOTONE
------------------------------------------------------------------------------------------------------------
CONTROLLO = 40 X>Y? 41 X<Y? 42 X=Y? 43 X>0? 44 X<0? 45 *INCn 46 END 47 LOOP 48 RTN 49 NOP
------------------------------------------------------------------------------------------------------------
MATEMATICHE = 50 (-) 51 (X) 52 (/) 53 (+) 54 CHS 55 Y^x 56 1/X 57 disp 58 SQRT 59 disp
-------------------------------------------------------------------------------------------------------------
CATASTA & VARIE = 60 DEL 61 ENTER 62 CLST (clr) 63 LASTX 64 X<>Y 65 RUOTA GIU' R!
66 CLX 67 *STOnn 68 *RCLnn 69 RUOTA SU R^
--------------------------------------------------------------------------------------------------------------
TRIGONOM & VARIE = 70 PI 71 SIN 72 COS 73 TAN 74 ASIN 75 ACOS 76 ATAN 77 disp 78 disp 79 disp
--------------------------------------------------------------------------------------------------------------
ESEGUI & VARIE = 80 SUB0 81 SUB1 82 SUB2 83 SUB3 84 SUB4 85 SUB5 86 disp 87 disp 88 *XEQnn 89 disp
--------------------------------------------------------------------------------------------------------------
LABEL & VARIE = 90 LBL0 91 LBL1 92 LBL2 93 LBL3 94 LBL4 95 LBL5 96 disp 97 disp 98 disp 99 ENDEND
--------------------------------------------------------------------------------------------------------------
*********************************************************************************************
HARDWARE
Si utilizza Arduino UNO, tastierino 16 tasti, display lcd 16x2 (I2C)
Possibilità di alimentazione a batteria.
*********************************************************************************************
*/
//***************************************
// librerie incluse
//---------------------------------------
// E' inclusa anche da sistema la <maht.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <EEPROM.h>
//******************************************************************************************
// E D I T O R dei programmi
//------------------------------------------------------------------------------------------
/*
I programmi si scrivono semplicemente digitando il codice relativo alla funzione,
si dovranno immettere sempre 2 caratteri per digitare uno si scrive "01".
L'EDITOR visualizza un numero progressivo (linea programma).
L'eventuale inizializzazione di variabili o di costanti si utilizzerà la
funzione RCL con la quale si richiama il registro da 1 a 19.
Nella fase inserimento dati potremmo immettere questi valori.
Nell'inserimento dati possiamo utilizzare anche i registri della catasta,
tenendo conto delle operazioni che svolgerà il programma
*/
//********************************************************************
const byte righe = 4; // per keypad
const byte colonne = 4;
//********************************************************************
byte key; // contiene il codice tasto premuto
byte codice =0; // codice operativo calcolato a partire da key (codice asccii)
byte codProg = 0; // codici programma
byte indirizzo = 0; // per indirizzare le memorie, i pin, le sub.
int poscifra = 0;// tiene conto delle cifre
boolean sciee = false; // true visualizza in notazione scientifica
boolean stato = false; // per la calcolatrice ( seconda funzione dei tasti)
//---------------------------------------------------------------
boolean looProg = false; // se true esegue loop
boolean se = true; // per le funzion if
boolean xeq = true; // per inserimento codice in Xeq_nn
boolean dati = true; // si inseriscono i dati in costanti
boolean prog = true; // si predispone per la programmazione
boolean sub = true; // per eseguire le subroutin
boolean endProg = false; // fine sub o programma
boolean stopProg = false; // per fermare il loop
boolean old = false; // per segnalare programma già in memoria risposta no
boolean si = true; // risposta si nelle scelte
boolean gira = false; // per sapere se sta elaborando il programma false non elabora
boolean uscitacalc = false; // per uscire da caLCOLATRICE
boolean arduQuadro = false; // si lavora con arduino quadro se true
boolean calcRPN = false; // si lavora in calcolatrice se true
//-----------------------------------------------------------------
float k1 = 10000000;// numero massimo visualizzabile poi si passa in visualizz scie
float k0 = 0.00001; // numero decimale piu piccolo visualizzabile
// per l'inserimento dei numeri decimali
int pdec = 0; // punto decimale
int ndec =0; // conta decimali
int fix = 4; //decimali di default
//*************************************************************************
// codici tastierino
//*************************************************************************
byte chiave [colonne][righe] =
{
{49,50,51,43}, // 1 2 3 +, *, sto, ins-linea
{52,53,54,45}, // 4 5 6 -, /, inc, corr-linea
{55,56,57,62}, // 7 8 9 2F , end-prog, esc, esc
{61,48,46,60} // En 0 . del, Xeq
};
//---------------------------------------------------------------
// pin assegnati al tastierino
//---------------------------------------------------------------
byte pinrighe[righe] = {4,5,6,7};
byte pincolonne[colonne] = {0,1,2,3};
// inizializza keypad e lcd
Keypad keypad = Keypad (makeKeymap(chiave),pinrighe,pincolonne,righe,colonne);
LiquidCrystal_I2C lcd(0x3F,16,2);
//**********************************************
// ARRAY DEL PROGRAMMA
//**********************************************
byte programma[100];
int riga = 0;
int ultimariga = 100;
int riga90 = 0;// qui si memorizza la riga inizio LBL
int riga91 = 0;
int riga92 = 0;
int riga93 = 0;
int riga94 = 0;
int riga95 = 0;
//----------------------------------------------------
// ----- variabili stak sub
int rigasubA = 0;
int rigasubB = 0;
int rigasubC = 0;
int rigasubD = 0;
int rigasubE = 0;
int rigasubF = 0;
int rigasubG = 0;
int rigasub = 0;
int rigaturn = 0;
//----------------------------------------------------
int rigaloop = 0; // punto di partenza dopo eventuale setup
//------------------------
//*** registri catasta
float regx = 0.0;
float regy = 0.0;
float regz = 0.0;
float regt = 0.0;
float lastx = 0.0; // recupero del registro x
float regu = 0.0;
// registri speciali
float regxs = 0.0; // per visualizzare la parte decimale della notazione sci
int esponente = 0; // esponente nella scientifica
float visore = 0.0; // accumula i valori immessi
//****************************************************************************
// STRINGHE
//****************************************************************************
String stringaMenu0 = String(' ');
String stringaMenu1 = String(' ');
String stringaUtente = String(' ');
//***********************
// memorie utente
//***********************
// registri per cicli for
int inc1 = 0; int cont1 = 0;
int inc2 = 0; int cont2 = 0;
int inc3 = 0; int cont3 = 0;
int inc4 = 0; int cont4 = 0;
int inc5 = 0; int cont5 = 0;
int inc6 = 0; int cont6 = 0;
//----------------------------
//--------------------------
float mem1 = 0.0;
float mem2 = 0.0;
float mem3 = 0.0;
float mem4 = 0.0;
float mem5 = 0.0;
float mem6 = 0.0;
float mem7 = 0.0;
float mem8 = 0.0;
float mem9 = 0.0;
float mem10 = 0.0;
float mem11 = 0.0;
float mem12 = 0.0;
float mem13 = 0.0;
float mem14 = 0.0;
float mem15 = 0.0;
float mem16 = 0.0;
float mem17 = 0.0;
float mem18 = 0.0;
float mem19 = 0.0;
//***********************
void setup()
{
lcd.init(); // initialize the lcd
lcd.clear();
lcd.backlight();
lcd.setCursor(0,0);
//lcd.print("1234567890123456");
lcd.print("ArduinoQuadro 13");
lcd.setCursor(0,1);
//lcd.print("1234567890123456");
lcd.print("Dicembre 2017 ");
delay (2000);
}
//**************************************************************
//**************************************************************
void loop()
{
inizializzazione(); // inizializzazione
iniarduino();
// scelte iniziali calcolatrice o arduQuadro menu
arduino();
while(arduQuadro == true)
{
nuovoprog(); // scelta se NEW (scrivere nuovo programma )
//oppure OLD programma in RAM
// finito la registrazione
// del programma o il caricamento da RAM
controllo(); // Si esegue il controllo e correzione
costanti();// Possiamo inserire dati nei registri
stringhe(); // per inseimento stringhe (da fare)
// pronto e si mette in attesa pressione tasto
pronto();
tasto();
// Esegue il programma utente
progUtente();
// uscita dal programma utente
fineprog();
}
// esegue come calcolatrice diretta
if (calcRPN == true) {uscitacalc = false;calcolatrice();}
}
//**** END LOOP ******************************************************
//********************************************************************
//******************************************
//******************************************
//** F U N Z I O N I **
//******************************************
//********************************************************************
void calcolatrice() // questa è un loop per utilizzare come calcolatrice
// manuale. Per uscire (uscitacalc = true;)
{
while (uscitacalc == false)
{
aggiornadisplay(); // sub che aggiona il display
tasto(); // attende pressione tasto
//-------------------------------------------------------------
// ****** si controlla lo stato della calcolatrice
// che può essere funzioni dirette o seconde funzioni 2F
if (stato == true)
{ // siamo in 2F )
funzioni_seconde();
}
if (stato == false)
{// siamo nelle funzioni dirette
funzioni_dirette();
}
}
calcRPN = false; // uscita da calcolatrice manuale
}
//***************** fine calcolatrice ******************************
// con queste si eseguono i comandi diretti da tastiera
void funzioni_dirette()
{
if (pdec == 0) // si deve scegliere fra numeri e numeri decimali
{
if ((codice >= 48) && (codice <= 57 ))
{impostanumero();}
}
if (pdec == 1) // è stato premuto il punto decimali
{
if ((codice >= 48) && (codice <= 57 ))
{impostanumerodec();}
}
// il codice è relativo ad una funzione oppure è stato attivato il tasto 2F
// per attivare le seconde funzioni
//seleziona la funzione la invia alla sub che la esegue e quindi ritorna
//
if (codice == 43)// somma
{somma();}
if (codice == 45) //sottrazione
{sottrazione();}
if (codice == 46) // punto decimali
{punto();} // con questa si pone a 1 la pdec
if (codice == 60)//cancella carattere
{del(); }
if (codice == 61)// ENTER
{enter();}
if (codice == 62) //seconda funzione 2f
{ stato = true;} // cambia stato
{}
return;
}
// ---- queste attivano le funzioni seconde della tastiera 2F (shift)
// vengono eseguite con la pressione del tasto 2F (shift) seguito dalla
// pressione del tasto relativo
//********* SE VIENE PREMUTO 2F (SHIFT) SI ESCE DA CALCOLATRICE MANUALE
//********** IN QUESTO CASO SI PASSA AL MENU' INIZIALE ARDU-QUADRO
void funzioni_seconde()
{
stato = false; // rimette false per tornare alle funzioni dirette
int codiceF2 = codice + 27;
//esegue una della funzioni F2 seconde
if (codiceF2 == 89)
{uscitacalc = true;}// uscita calcolatrice MANUALE
if (codiceF2 == 70)// moltiplicazione
{moltiplicazione();}
if (codiceF2 == 72) //divisione
{divisione();}
if (codiceF2 == 87) // Xeq esegue funzione da 1 a ...
{Xeq_nn();} // questa esegue una delle funzioni richiamabili
if (codiceF2 == 88)//Lastx ( recupera x )
{last_x(); }
if (codiceF2 == 75)// x<>y scambio x con y
{scambio();}
if (codiceF2 == 73) // R! scorre catasta
{ ruota(); }
if (codiceF2 == 81) //cambia segno (moltiplica x per -1)
{cambiasegno();}
if (codiceF2 == 76) // seno di x angolo in RADIANTI
{lastx = regx; regx = sin (regx);}
if (codiceF2 == 77)//tangente x angolo in x in RADIANTI
{ lastx = regx; regx = tan (regx);}
if (codiceF2 == 78)// coseno x angolo in x in RADIANTI
{ lastx = regx; regx = cos (regx);}
if (codiceF2 == 79) //radice quadrata
{ lastx = regx; regx = sqrt (regx);}
if (codiceF2 == 80)
// potenza eleva y alla x
//pow(base, exponent)
//base: numero (tipo float)
//exponent: la potenza a cui è elevata la base (tipo float)
// si utilizza x ed y della catasta
{ lastx = regx; regx = pow (regy, regx); }
if (codiceF2 == 84)//fix decimali
{visfix(); }
if (codiceF2 == 82)// STO n
{sto_n();}
if (codiceF2 == 83) //RCL n
{rcl_n(); }
codice = 0;
visore = 0;
return;
}
//*********************************************************************
//******** ARDUINO QUADRO *********************************************
//*********************************************************************
void inizializzazione()
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Inizializzazione");
delay (500);
//*******************************************************
stringaMenu0 = String(" ");
stringaMenu1 = String(" ");
//*******************************************************
old = false; // per segnalare programma già in memoria risposta no
si = true; // risposta si nelle scelte
gira = false; // se gira il programma va a true
arduQuadro = false;
calcRPN = false;
}
//****************************************************************
void iniarduino()
{
stringaMenu0 = String(" ");
stringaMenu1 = String(" ");
// registri per cicli for
inc1 = 0; cont1 = 0;
inc2 = 0; cont2 = 0;
inc3 = 0; cont3 = 0;
inc4 = 0; cont4 = 0;
inc5 = 0; cont5 = 0;
inc6 = 0; cont6 = 0;
//-------------------------------
rigasubA = 0;
rigasubB = 0;
rigasubC = 0;
rigasubD = 0;
rigasubE = 0;
rigasubF = 0;
rigasubG = 0;
rigasub = 0;
rigaturn = 0;
//------------------------------
riga = 0;
ultimariga = 100;
riga90 = 0;// qui si memorizza la riga inizio LBL
riga91 = 0;
riga92 = 0;
riga93 = 0;
riga94 = 0;
riga95 = 0;
//-------------------
//---------------------------------------------------
rigaloop = 0;
//----------------------------------------------------
looProg = false; // se true esegue loop
se = true; // per le funzion if
xeq = true; // per inserimento codice
dati = true; // si inseriscono i dati in costanti
prog = true; // si predispone per la programmazione
sub = true; // per eseguire le subroutin
endProg = false; // fine sub o programma
stopProg = false; // per fermare il loop
//--------------------------------------------------------------------
old = false; // per segnalare programma già in memoria risposta no
si = true; // risposta si nelle scelte
gira = false; // se gira il programma va a true
//--------------------------------------------------------------------
}
// con questa si sceglie se usare come
// calcolatrice RPN oppure come arduinoQuadro
//
void arduino()
{
//stringaMenu0 = String("1234567890123456");
stringaMenu0 = String("arduinoQuadro-13");
stringaMenu1 = String("1=CALC 3= arduQ ");
sceltemenu();
if (old == true){arduQuadro = true; calcRPN = false;} // si programma come arduQuadro
else {arduQuadro = false; calcRPN = true;}/// si usa come calcolatrice
}
void fineprog()
{
stringaMenu0 = String("Fine programma");
stringaMenu1 = String("1=STOP 3=CONT"); // si stop
sceltemenu();
if (si == true) {calcRPN = true; arduQuadro = false;}
}
// con questa si esegue un programma esistente
// si corregge un programma esistente
// oppure si sceglie di scriverne uno nuovo
void nuovoprog()
{
stringaMenu0 = String("Menu programma ");
stringaMenu1 = String("1=NEW - 3=OLD");
sceltemenu();
if (old == true){leggiprog();} // con old a true si legge il programma dalla EPROM
if (old == false) {scritturaprog();} // con old false si scrive nuovo programma
}
void sceltemenu()
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(stringaMenu0);
lcd.setCursor(0,1);
lcd.print(stringaMenu1);
boolean menu = true;
old = false; // tasto 3 risposta no
si = false; // tasto 1 risposta si
while (menu == true)
{
tasto();
if (codice == 49){si = true; menu = false;} // SI
if (codice == 51){old = true; menu = false; } // NO
}
}
//-------------------------------------------------------
void pronto()
{lcd.clear();
lcd.setCursor(0,1);
lcd.print("Premi un tasto ");
}
//*********************************************************************
//*********************************************************************
void tasto()
{
key = 0; // azzera variabile tasto del tasterino e
//************* attende la pressione di un tasto sul tastierino
while (key == 0) // rimane qui fino alla pressione di un tasto
{
key = keypad.getKey();
codice = key;
}
}
//*********************************************************************
void stringhe()// per inseimento stringhe (da fare)
{
stringaMenu0 = String("Stringhe ? ");
stringaMenu1 = String("1= SI - 3= NO");
sceltemenu();
if (old == true){return;} // non si inseriscono stringhe
// qui da fare inserimento stringhe
inseralfa();
}
//******************* EDITOR SCRITTURA PROGRAMMI UTENTE ******************
void scritturaprog()
// questa scrive e memorizza il programma UTENTE
{
// cancellazione programma in memoria
for (int i = 0; i < 100; i++)
{codProg = 0;
EEPROM.write(i, codProg);
}
//-------------------------------------
while ( prog == true)
{
inidisplay(); // editor scrittura codici
editor();
prog = false;
}
}
//********************************************************************
void inidisplay()
{
//INIZIALIZZAZIONE EDITOR
lcd.init();
lcd.clear();
lcd.backlight();
lcd.setCursor(0,0);
lcd.print("ARDUINO EDITOR");
lcd.setCursor(0,1);
lcd.print("Inserire codice");
delay (2000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("C>: ");
}
//********************************************************************
void editor() // QUI SI SCRIVONO I CODICI PROGRAMMA UTENTE
{
riga = 0;
int i=0;
while ( i<100)
{
impostacodice();
programma[i] = codProg;
riga = i;
i = i+1;
if (codice == 62)
{
ultimariga = i;
// programma[i] = 99;//ultimariga
i = 100;
}
editordisplay();
}
}
//***************************************************************************
// F I N E SCRITTURA PROGRAMMA
//***************************************************************************
// CON QUESTA SI RIVEDE IL PROGRAMMA
//e consente la correzione di passi di programma
void controllo()
{
prelabora();
stringaMenu0 = String("Controllo ? ");
stringaMenu1 = String("1= SI - 3= NO");
sceltemenu();
if (old == true){return;} // non esegue il controllo
// esegue il controllo
lcd.clear();
lcd.setCursor(0,0);
//ultimariga = riga;
int c = 0;
while (c<ultimariga)
{
codProg = programma[c];
riga = c;
editordisplay();
lcd.setCursor(0,1);
// lcd.print("1234567890123456");
lcd.print("cont> end> corr>");
tasto();
if (codice == 45) // correzione linea TASTO (-)
{
// scrivere la correzione
// questo tipo di correzione sostituisce
// la riga errata con altra corretta
// lasciando invatiato il resto del programma
//** PER CANCELLARE INTRODURRE UNA NOP **** codice 49
// la NOP non farà nulla e non altera il programma
// ma occorre tener conto delle istruzioni precedenti o
// seguenti che potrebbero utilizzare le informazioni
// della riga cancellata (if, rcl, sto, pin ...)
impostacodice();
programma[c] = codProg;
c = c-1; // per rivedere la correzione effettuata
lcd.setCursor(0,1);
// lcd.print("1234567890123456");
lcd.print("correzione OK ");
delay (300);
}
if (codice == 43) // inserimento linea TASTO (+)
{
// si preme + (43) sul numero riga che si vuole inserire
// ci chiede d'impostare il nuovo codice da inserire
// quindi sposta tutte le linee aggiungento una riga
int ins = c; // numero linea da inserire
lcd.setCursor(0,1);
// lcd.print("1234567890123456");
lcd.print("ins new codice ");
delay (300);
impostacodice();
int newCodice = codProg;
// aggiunge un posto all'array
ultimariga = ultimariga +1;
int i = ultimariga;
// ciclo che parte dal fondo e sposta tutte le linee
// fino alla riga da inserire
while ( ins < i )
{
programma[i] = programma[ i -1];
i = i-1;
}
// ora inserisce il nuovo codice al suo posto
programma[ins] = newCodice;
// conferma correzione
c = ins-1;
lcd.setCursor(0,1);
lcd.print("correzione OK ");
delay (300);
}
// tasti funzione
if (codice == 62){ c = ultimariga;} // esce dal controllo
if (codice == 49) { c = c+1;}// avanti (1)
if (codice == 51) {c = c-1;} // indietro (3)
}
salvaprog();
// se vogliamo possiamo salvarlo nella EEPROM
}
//***************************************************************
void salvaprog() // si scrive il programma in memoria
{
stringaMenu0 = String("Salva in RAM ");
stringaMenu1 = String("1= SI - 3= NO");
sceltemenu();
if (old == true){return;}
if (old == false)
{
for (int i = 0; i < ultimariga; i++)
{codProg = programma[i];
EEPROM.write(i, codProg);
}
lcd.setCursor(0,1);
// lcd.print("1234567890123456");
lcd.print("Salvataggio OK ");
delay (300);
}
}
void leggiprog() // qui il codice per leggere il programma in memoria
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Legge prog da RAM");
for (int i = 0; i < 100; i++)
{ codProg = EEPROM.read(i);
programma[i] = codProg;
}
prelabora(); // predispone il programma letto da ram
}
//****************************************************************
void editordisplay()
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print("n: ");
lcd.setCursor(4,0);
lcd.print (riga);
lcd.setCursor(10,0);
lcd.print (codProg);
if (codice == 62)
{
lcd.setCursor(0,1);
lcd.print("fine programma");
delay (3000);
}
}
//*********************************************
void aggiornadisplay()
{
//***************
// mostra display
//---------------
// si esegue il controllo se visualizzare in notazione sci o con fix
double testx = regx;
if (testx < 0) testx = testx*-1;
if (testx > k1) sciee = true;
if (testx < k0) sciee = true;
if (testx == 0) sciee = false;
lcd.clear();
lcd.setCursor(0,0);
lcd.print("X:");
lcd.setCursor(4,0);
if (sciee == true)
{
sci(); // sub per notazione scientifica
lcd.print(regxs,5);
lcd.setCursor(14,0);
lcd.print (esponente);
}
else lcd.print(regx,fix); // visualizzazione normale
lcd.setCursor(0,1);
if (stato == false){lcd.print("1:");}
if (stato == true) {lcd.print("2:");}
lcd.setCursor(4,1);
lcd.print(visore,fix);
sciee = false;
}
// questa sub prepara "regxs" ed "esponente" per visualizzare in notazione sci
// ATTENZIONE regxs serve solo per la visualizzazione di numeri in notazione
// scientifica in abbinamento al registro "esponente"
// non coinvolgere direttamente nei calcoli i due rappresentano comunque
// il contenuto di "regx" che deve essere utilizzato per il calcolo.
void sci()
{
lastx = regx;
double numero = regx;
int segno = 1;
int segnoe = 1;
esponente = 0;
// se il numero è negativo si trasforma in positivo
// ma si mette a -1 la variabile segno, ci servirà
// per ritornare a negativo dopo aver trovato
// il valore dell'esponte con la log10(numero)
if (numero < 0) {numero = numero *-1; segno = -1;}
double numlog = log10(numero); // si ottiene il logaritmo del numero
// N,xxxxx preleveremo la parte
// intera che rappresenta l'esponente
esponente = int( numlog); // adesso abbiamo il numero intero esponente
numero = numero*segno; // si ripristina il giusto segno
// si esegue il controllo se l'esponente è negativo e si
//esegue la stessa procedura fatta per il numero
if (esponente <0){esponente = esponente *-1; segnoe = -1;}
//-----------------------------------------------------------------------
// se segnoe è negativo il numero è molto piccolo
if (segnoe == -1){regxs = numero * pow(10,esponente);}
else regxs = numero / pow(10,esponente); //altrimenti numero molto grande
//------------------------------------------------------------------------
esponente = esponente * segnoe; // si ripristina il giusto segno
// all'esponente
}
//*********************************************************
// con questa si inseriscono dati nei registri
//*********************************************************
void insertdati()
{
if (pdec == 0) // si deve scegliere fra numeri e numeri decimali
{
if ((codice >= 48) && (codice <= 57 ))
{impostanumero();}
}
if (pdec == 1) // è stato premuto il punto decimali
{
if ((codice >= 48) && (codice <= 57 ))
{impostanumerodec();}
}
if (codice == 43)// sto-n memorizza x nel reg indicato da visore
{indirizzo = visore; sto_n(); lcd.print(" ok "); delay (300);}
if (codice == 45) // inserire in X numero da raggiungere,
// attenzione si usano interi 32767 -32768
{gira = false; indirizzo = visore; inc_n();lcd.print(" ok "); delay (300);}
if (codice == 46) // punto decimali
{punto();} // con questa si pone a 1 la pdec
if (codice == 60)//cancella carattere
{del(); }
if (codice == 61)// ENTER
{enter();}
if (codice == 62) //fine dati
{ }
return;
}
void inseralfa()
{
lcd.clear();
lcd.setCursor(0,0);
stringaUtente = ("");
while (codice != 62)
{
impostacodice();
char codAlfa = codProg;
String stringa0 = String(codAlfa);
stringaUtente = String(stringaUtente + stringa0);
lcd.clear();
lcd.setCursor(0,0);
lcd.print(stringaUtente);
}
alfadisplay();
}
void alfadisplay()
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(stringaUtente);
if (codice == 62)
{
lcd.setCursor(0,1);
lcd.print("string ok ");
delay (2000);
}
}
void costanti()
{
stringaMenu0 = String("Ins. Dati ? ");
stringaMenu1 = String("1= SI - 3= NO");
sceltemenu();
if (old == true){return;} // salta inserimento dati
// inseimento dati valori
dati = true;
while ( dati == true)
{
aggiornadisplay(); // sub che aggiona il display
tasto();
insertdati();
if (codice == 62){dati = false;}
}
lcd.clear();
lcd.setCursor(0,0);
lcd.print("OK dati inseriti");
delay (1000);
}
//***********************************************************************
// INTERPETRA ED ELABORA IL PROGRAMMA UTENTE
//***********************************************************************
void prelabora()
{
//*********** PRE ELABORAZIONE *************************************
// questa parte legge tutto il programma e cerca le LBL (90,91,92,93,94,95)
// cerca anche se esiste l'istruzione loop (47) in questo caso
// pone a true la looProg ed il programma UTENTE continurà a girare
// fino ad un reset esterno.
looProg = false;
rigaloop = 0;
for (int c = 0; c<ultimariga; c++) // prepara programma
{codProg = programma[c];
if ( codProg == 90){riga90 = c;} // memorizza inizio LBL
if ( codProg == 91){riga91 = c;}
if ( codProg == 92){riga92 = c;}
if ( codProg == 93){riga93 = c;}
if ( codProg == 94){riga94 = c;}
if ( codProg == 95){riga95 = c;}
if ( codProg == 47){looProg = true; rigaloop = c;}// quando trova end riparte da rigaloop
//if ( codProg == 99){ultimariga = c;}// memorizza l'ultima riga
}
}
//**************************************************************************
void progUtente()
{
gira = true;
prelabora();
//*************************************************************************
//*************************** elaborazione programma **********************
//*************************************************************************
if (looProg == true)
{
int cloop = rigaloop;
rigaloop = 0;
cicloprogramma(); // esegue la prima volta il programma da zero
rigaloop = cloop;
}
if (looProg == true)
{
while (looProg == true)
cicloprogramma(); // ora il programma gira sempre
// interrupt
// con pulsante
// che ferma il loop
// mettendo looProg a false
}
else {cicloprogramma();}
gira = false; // fine programma
while(codice == 62)
{
aggiornadisplay(); // sub che aggiona il display
tasto();
}
}
//**************************************************************************
void cicloprogramma()
{
int c = rigaloop;
rigasub = 0;
codProg = 0;
while (codProg != 46) // quando END esce
{
codProg = programma[c];
riga = c;
se = false;
//----------------------------------------------------
if ( codProg == 80){ rigasub = c; staksub(); c = riga90;}
if ( codProg == 81){ rigasub = c; staksub(); c = riga91;}
if ( codProg == 82){ rigasub = c; staksub(); c = riga92;}
if ( codProg == 83){ rigasub = c; staksub(); c = riga93;}
if ( codProg == 84){ rigasub = c; staksub(); c = riga94;}
if ( codProg == 85){ rigasub = c; staksub(); c = riga95;}
//-----------------------------------------
if (codProg == 48){ stak(); c = rigaturn;}
eseguiprog();
if (se == true) { c = c+1;}
// se una if è vera torna true
// e quindi si salta la riga successiva
// altrimenti il prog continua normale
c = c+1;
}
}
//*********************************************************
// ---- pila per le sub ----------
void staksub() // fa salire in catasta stak delle sub il valore in rigasub
{
rigasubG = rigasubF;
rigasubF = rigasubE;
rigasubE = rigasubD;
rigasubD = rigasubC;
rigasubC = rigasubB;
rigasubB = rigasubA;
rigasubA = rigasub;
}
void stak () // FA SCENDERE LO STAK E RESTITUISCE LA RIGA SUB
{
rigaturn = rigasubA;
rigasubA = rigasubB;
rigasubB = rigasubC;
rigasubC = rigasubD;
rigasubD = rigasubE;
rigasubE = rigasubF;
rigasubF = rigasubG;
}
//******************************************
void eseguiprog()
{
// esegue le funzioni
funzioni();
aggiornadisplay();
}
// ************************************************************************
//*************************************************************************
//************************************************
// queste sono FUNZIONI chiamate dal programma
//***********************************************
// si distinguono dal "codice" che in questo caso diventa "codProg"
void funzioni() // ESEGUIBILI DA PROGRAMMA UTENTE
{
// ------------------------------------------------
if (( codProg >= 0) && ( codProg < 20))
{ indirizzo = codProg; visore = codProg;}
// i numeri compresi da 0 a 19
// sono indirizzi per le funzioni che li
// richiedono stoxnn, rclxnn, pin ....
//-------------------------------------------------
// **** per la PRINT da programma
if ( codProg == 20) // pulisce il display e scrive la stringa utente
// attende la pressione di un tasto per continuare
// visualizza registro x
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print("X:");
lcd.setCursor(4,0);
lcd.print(regx);
lcd.setCursor(0,1);
lcd.print(stringaUtente);
tasto();
}
// *** per effettuare input da programma
if (codProg == 21) { costanti(); } // inserimento dati
//-------------------------------------------------
// *** ARDUINO *****
if (codProg == 30) // pin nn input
{ pinMode ( indirizzo, INPUT);}
if (codProg == 31) // pin nn output
{ pinMode ( indirizzo, OUTPUT);}
if (codProg == 32) //--pin nn HIGH
{ digitalWrite( indirizzo, HIGH); }
if (codProg == 33) //--pin nn LOW
{ digitalWrite( indirizzo, LOW); }
if (codProg == 34)//-- legge il pin e inserisce il valore in x
{regx = digitalRead (indirizzo );}
if (codProg == 35) //-- legge il pin ed inserisce il valore in x
{
int pin = 0;
if (indirizzo == 0) {pin = A0;}
if (indirizzo == 1) {pin = A1;}
if (indirizzo == 2) {pin = A2;}
if (indirizzo == 3) {pin = A3;}
regx = analogRead(pin);}
if (codProg == 36) // disponibile
{ analogWrite (indirizzo, regx); }
if (codProg == 37) // delay
{ delay_mm(); } // in visore codice da 01 a 06
//1 = 5 mms, 2= 10, 3= 50, 4= 250, 5=500, 6 = 1000 mms
if (codProg == 38) // TONE (PIN,FREQUENZA,DURATA)
// in indirizzo il pin nel regx la frequenza
// in y porre zero ( per fermare occorre la NOTONE)
// oppure inserire in y la durata
{ if (regy == 0){ tone(indirizzo, regx);}
else {tone(indirizzo,regx, regy);}
}
if (codProg == 39) //
{ noTone( indirizzo); }
//-----------------------------------------------------
// **** CONTROLLO ******
if (codProg == 40) //---controlla se x > di y
{if ( regx > regy ){se = true;}}
if (codProg == 41) //--- controlla se x < di y
{if (regx < regy) {se = true;}}
if (codProg == 42) //---controlla se x = y
{if (regx == regy){se = true;}}
if (codProg == 43) //----controlla se x è > di 0
{ if ( regx > 0){se = true;}}
if (codProg == 44)//--- controlla se x è < di 0
{ if ( regx < 0){se = true;}}
if (codProg == 45)//
{inc_n(); }
// ---- codici particolari ---------------------------------------
if (codProg == 46) // END FINE PROGRAMMA UTENTE
{}// da inserire prima di eventuali sub
// esegue uscita dal programma
// se esiste l'istruzione loop
// rimanda alla rigaloop
if (codProg == 47)// LOOP programma
{} // memorizza la riga inizio loop
// del programma che puo essere diversa
// dalla 0
if (codProg == 48)// RTN ritorno dalle sub
{}
if (codProg == 49)//
{} // NOP non fa nulla
//--------------------------------------------------------------------
// ****** MATEMATICHE *****
if (codProg == 50) //sottrazione
{sottrazione();}
if (codProg == 51) // moltiplicazione
{moltiplicazione();}
if (codProg == 52) // divisione
{divisione();}
if (codProg == 53)// somma
{somma();}
if (codProg== 54) //cambia segno (moltiplica x per -1)
{cambiasegno();}
if (codProg == 55) // potenza eleva y alla x
{ lastx = regx; regx = pow (regy, regx); }
//pow(base, exponent)
//base: numero (tipo float)
//exponent: la potenza a cui è elevata la base (tipo float)
// si utilizza x ed y della catasta
if (codProg == 56) // 1/x
{unosux();}
if (codProg == 57) // intero di x
{}// {interox();}// da fare
if (codProg == 58) // radice di x
{ lastx = regx; regx = sqrt (regx);}
if (codProg == 59)// disponibile
{ }
//----------------------------------------------------------
// ***** CATASTA OPERATIVA *****
if (codProg == 60)// cancella
{del();}
if (codProg == 61)// ENTER
{enter();}
if (codProg == 62)// cancella registri e catasta
{ cancella();} //CLST
if (codProg == 63) //Lastx ( recupera x )
{last_x(); }
if (codProg == 64)// x<>y scambio x con y
{scambio();}
if (codProg == 65) // abbassa catasta R!
{ ruota();}
if (codProg == 66)// cancella registo x
{lastx = regx; regx = 0.0;}
if (codProg == 67)// memorizza x nel nn indicato nel precedente codice
{sto_n();}
if (codProg == 68)// richiama in x nn indicato nel precedente codice
{rcl_n();}
if (codProg == 69)// ruota su catasta
{ ruotaSU(); }
//----------------------------------------------------------
// **** TRIGONOMETRICHE ANGOLO IN RADIANTI *****
if (codProg == 70) // PI GRECO
{ lastx = regx; regx = PI;}// richiama pigreco
if (codProg == 71) // seno di x angolo in RADIANTI
{lastx = regx; regx = sin (regx);}
if (codProg == 72)// coseno x angolo in x in RADIANTI
{ lastx = regx; regx = cos (regx);}
if (codProg == 73)//tangente x angolo in x in RADIANTI
{ lastx = regx; regx = tan (regx);}
if (codProg == 74)// arco seno di x
{arcosen_x();}
if (codProg == 75)// arco coseno di x
{arcocos_x();}
if (codProg == 76)// arco tangente di x
{arcotan_x();}
//---------------------------------------------------------------
// **** FUNZIONI PER FLUSSO SUB GOTO *****
// la 88 Xeq_nn richiama altre funzioni aggiuntive
if (codProg == 80)
{ }// chiamata sub0 (90)
if (codProg == 81)
{ } // chiamata sub1 (91)
if (codProg == 82)
{ } // chiamata sub2 (92)
if (codProg == 83) // // chiamata sub3 (93)
{ }
if (codProg == 84) // // chiamata sub4 (94)
{ }
if (codProg == 85) // // chiamata sub5 (95)
{ }
if (codProg == 86) // disp
{ }
if (codProg == 87) // disp
{ }
if (codProg == 88) // esegue la funzione nn da 1 a nn
{ Xeq_nn();}
// alle funzioni scritte se ne possono aggiungere
// altre.
if (codProg == 89) // disp
{ }
//---------------------------------------------------------------
// **** funzioni flusso LABEL DELLE SUB E DEL GOTO *****
// LA 99 END-END chiude il programma
if (codProg == 90)
{ }// label LBL0
if (codProg == 91) // label
{}
if (codProg == 92)// label
{ }
if (codProg == 93) // label
{ }
if (codProg == 94) // label
{}
if (codProg == 95) // label
{ }
if (codProg == 96) // DISP
{}
if (codProg == 97) // DISP
{ }
if (codProg == 98) // DISP
{}
if (codProg == 99) // end-end
{codProg = 46; } // end
//----------------------------------------------------------------
return;
}// fine chiamata funzioni di programma utente
//****************************************************************
//****************************************************************
//****************************************************
// ESEGUE LE FUNZIONI CHIAMATE
//****************************************************
//****************************************************************
// parte intera di un numero si scrive su visore
void impostacodice()
{
xeq = true;
while(xeq == true)
{
byte cifra = 0;
byte cifra2 = 0;
tasto();
if (codice == 62){xeq = false;}
if ((codice >= 48) && (codice <= 57 ))
{
cifra = codice - 48;
}
tasto();
if (codice == 62){xeq = false;}
if ((codice >= 48) && (codice <= 57 ))
{
cifra2 = codice - 48;
codProg = cifra*10 + cifra2;
if ((codProg >= 0 )&& (codProg < 100))
{xeq = false;}
}
if (codice == 43){}
if (codice == 45){}
if (codice == 46){}
if (codice == 60){}
if (codice == 61){}
}
}
//---------------------------------------------------------------
void impostanumero()
{
poscifra = poscifra +1;
if (poscifra < 9)
{int cifra = codice - 48;
visore = visore * 10 + cifra;
}
else { codice = 61;}
}
//****************************************************************
// si scrive su visore il numero decimale
void impostanumerodec()
{
ndec = ndec+1;
if (fix >= ndec)
{
float cifradec = (codice - 48.0);
if (ndec == 1) {visore = visore + (cifradec /10);}
if (ndec == 2){visore = visore + (cifradec /100);}
if (ndec == 3){visore = visore + (cifradec /1000);}
if (ndec == 4){visore = visore + (cifradec /10000);}
if (ndec == 5){visore = visore + (cifradec /100000);}
}
else { codice = 61;}
}
//----------------------------------------------------------
//***************************************************************
void unosux() //
{
if (regx == 0)return;
regx = ( 1 /regx);
}
void somma()//
{
// somma il contenuto di x con y
// ricorda in lastx e last y i due valori
// azzera la y in x abbiamo il risultato
lastx = regx;
regx = (regx + regy);
regy = regz;
regz = regt;
regt = regu;
del();
}
void sottrazione()//
{
// sottrae x da y
lastx = regx;
regx = (regy - regx);
regy = regz;
regz = regt;
regt = regu;
del();
}
// punto decimali
void punto()
{
pdec = 1;
ndec = 0;
codice =0;
}
//cancella carattere
void del() //60
{
visore = 0;
poscifra =0;
codice = 0;
pdec = 0;
ndec = 0;
}
//61 da codice
void enter()
{
regu = regt;
regt = regz;
regz = regy;
regy = regx;
regx = visore;
//lastx = regx;
// prima sale la catasta
// poi azzera
del();
}
// moltiplicazione //
void moltiplicazione()
{
lastx = regx;
regx = (regy * regx); // esegue la moltiplicazione
regy = regz;
regz = regt;
regt = regu;
del();
}
//divisione //
void divisione()
{
if (regx == 0) return; //******* divisione per 0
lastx = regx; // prima salva in lastx il valore di x
regx = (regy / regx); // esegue la divisione
regy = regz;
regz = regt;
regt = regu;
del();
}
// clr // CLST
void cancella() //cancella catasta e visore
{
regu = 0.0;
regt = 0.0;
regz = 0.0;
regy = 0.0;
regx = 0.0;
lastx = 0.0;
visore = 0.0;
poscifra =0;
codice = 0;
pdec = 0;
ndec = 0;
}
void cancella_mem()// cancella memorie utente
{
mem1 = 0.0;
mem2 = 0.0;
mem3 = 0.0;
mem4 = 0.0;
mem5 = 0.0;
mem6 = 0.0;
mem7 = 0.0;
mem8 = 0.0;
mem9 = 0.0;
mem10 = 0.0;
mem11 = 0.0;
mem12 = 0.0;
mem13 = 0.0;
mem14 = 0.0;
mem15 = 0.0;
mem16 = 0.0;
mem17 = 0.0;
mem18 = 0.0;
mem19 = 0.0;
}
//Lastx
void last_x()
{
regu = regt;
regt = regz;
regz = regy;
regy = regx;
regx = lastx;
}
// x<>y scambio
void scambio()
{
float scambio = regx;
regx = regy;
regy = scambio;
}
//ruota giu la catasta
void ruota()
{
float ruota = regx;
regx = regy;
regy = regz;
regz = regt;
regt = regu;
regu = ruota;
}
//ruota SU la catasta
void ruotaSU()
{
float ruota = regu;
regu = regt;
regt = regz;
regz = regy;
regy = regx;
regx = ruota;
}
//cambiosegno
void cambiasegno()
{
lastx = regx; regx = regx * -1;
}
// FIX----- scelta numero decimali dopo il punto da 0 a 5
void visfix()
{ if (( visore < 0 )|| (visore > 5)) return;
else fix = visore;
}
void arcosen_x() // funzione XEQ 1 ritorna angolo in x in RADIANTI
{ if ((regx < -1)||( regx > 1)) return;
{lastx = regx; regx = asin (regx);}
}
void arcocos_x() // funzione XEQ 3 ritorna angolo in x in RADIANTI
{ if ((regx < -1)|| ( regx > 1)) return;
{lastx = regx; regx = acos (regx);}
}
void arcotan_x() // funzione XEQ 2 ritorna angolo in x in RADIANTI
{lastx = regx; regx= atan (regx);}
// converte x da sessagesimale a sessadecimale
// solo il registro x della catasta viene utilizzato
void sess_sedec() // FUNZIONE
{
lastx = regx;
float a = regx;
int b = int(a); // i gradi
float c = (a-b)*100;
int d = int(c);
float pri = d/60.0; // primi
float sec = (c-d)/36.0; // i secondi
regx= (b+pri+sec);
}
// converte x da sessadecimali a sessagesimali
// solo il registro x della catasta viene utilizzato
void sedec_sessa() // FUNZIONE XEQ 5
{
lastx = regx;
float a = regx;
int b = int(a); // i gradi
float c = (a-b)*60;
int d = int(c); // i primi
float pri = d/100.0;
float sec = (c-d)*6/1000.0; // i secondi
regx= (b+pri+sec);
}
// da polari a rettangolari inserire in x l'angolo alfa
// in gradi RADIANTI
// inserire in y la magnitudine
// restituisce le cordinate in x e y
void P_R()
{
double magni = regy;
double alfa = (regx);
if (magni < 0)return;
if (alfa > (2*PI))return;
if (alfa < 0 )return;
regx = magni*cos(alfa);
regy = magni*sin(alfa);
}
// da rettangolari a polari insere in x la coordinata x ed in y la cooordinata y
// restituisce in y la distanza
// e restituisce in x angolo in RADIANTI
//
void R_P()
{
double alfa = 0;
double magni = sqrt((regx*regx)+ (regy*regy));
alfa = atan2(regy,regx);
regx = alfa;
regy = magni;
}
// questa sub serve ad inserire un numero molto grande o molto piccolo
// in catasta inserendo in y il valore n.nnnnn ed in x l'esponente base 10
void inputsci()
{
double numero = regy;
double esp = regx;
regx = numero * pow(10,esp);
regxs = regx;
esponente = esp;
sciee = true;
}
void fact() // funzione 19 fattoriale *****
{
int numero = regx;
double fact = 1.0;
regx = fact;
if ((numero < 1)||(numero > 31)) return;
else {
for ( int i = numero; i > 1; i--)
{fact = fact * i;}
regx = fact;
}
} // end fact
//---------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
// STO n SUB PER MEMORIZZARE IL CONTENUTO DI X
//NEL REGISTRO INDICATO IN VISORE DA 1 A 19
// MA SE OCCORRE SI PUO' AUMENTARE LE MEMORIE UTENTE
// IN QUEL CASO OCCORRE VARIARE ANCHE LA SUB RCL
// E LA SUB CHE CANCELLA IL CONTENUTO MEMORIE UTENTE
// CIOE LA 12 cancella_mem
void sto_n()
{
int mem = visore;
if (( mem < 1 )||(mem > 19)) return;
switch (mem)
{
case 1:
mem1 = regx;
break;
case 2:
mem2 = regx;
break;
case 3:
mem3 = regx;
break;
case 4:
mem4 = regx;
break;
case 5:
mem5 = regx;
break;
case 6:
mem6 = regx;
break;
case 7:
mem7 = regx;
break;
case 8:
mem8 = regx;
break;
case 9:
mem9 = regx;
break;
case 10:
mem10 = regx;
break;
case 11:
mem11 = regx;
break;
case 12:
mem12 = regx;
break;
case 13:
mem13 = regx;
break;
case 14:
mem14 = regx;
break;
case 15:
mem15 = regx;
break;
case 16:
mem16 = regx;
break;
case 17:
mem17 = regx;
break;
case 18:
mem18 = regx;
break;
case 19:
mem19 = regx;
break;
}
visore = 0;
} // fine void sto_n
//-------------------------------------------------------------------------------------------------
//RCL richiama in x uno dei registri
void rcl_n()
{
indirizzo = visore;
int mem = indirizzo;
if (( mem < 1 )||(mem > 19)) return;
switch (mem)
{
case 1:
{ visore = mem1; enter();}
break;
case 2:
{visore = mem2; enter();}
break;
case 3:
{visore = mem3; enter();}
break;
case 4:
{visore = mem4; enter();}
break;
case 5:
{visore = mem5; enter();}
break;
case 6:
{visore = mem6; enter();}
break;
case 7:
{visore = mem7; enter();}
break;
case 8:
{visore = mem8; enter();}
break;
case 9:
{visore = mem9; enter();}
break;
case 10:
{visore = mem10; enter();}
break;
case 11:
{visore = mem11; enter();}
break;
case 12:
{visore = mem12; enter();}
break;
case 13:
{visore = mem13; enter();}
break;
case 14:
{visore = mem14; enter();}
break;
case 15:
{visore = mem15; enter();}
break;
case 16:
{visore = mem16; enter();}
break;
case 17:
{visore = mem17; enter();}
break;
case 18:
{visore = mem18; enter();}
break;
case 19:
{visore = mem19; enter();}
break;
}
}
//-------------------------------------------------------------------------------------------------
void Xeq_nn()
{ int mem = visore;
if (( mem < 1 )|| ( mem > 99)) return;
switch (mem)
{
case 1:
{arcosen_x();}// arcoseno di x in radianti
break;
case 2:
{arcotan_x();}// arcotangente ritorna angolo in x in RADIANTI
break;
case 3:
{arcocos_x();} // arco coseno di x in radianti
break;
case 4:
sess_sedec(); // converte da sessagesimali a sessadecimali
break;
case 5:
sedec_sessa(); // converte da sessadecimali a sessagesimali
break;
case 6:
{ lastx = regx; regx = PI;}// richiama pigreco
break;
case 7:
// converte da radianti in sessagesimali
{lastx = regx; regx = regx*180.0/PI; sedec_sessa();}
//Log10
// {lastx = regx; regx = log10(regx);}
break;
case 8:
// da gradi sessagesimali a radianti
{lastx = regx; sess_sedec();regx = regx*PI/180.0;}
break;
case 9:
// cancella registri e catasta
{ cancella();} //CLST
break;
case 10:
R_P (); // da rettangolari a polari
break;
case 11:
P_R(); // da polari a rettangolari p>=0 e alfa >=0 e <= pi/2
break;
case 12:
cancella_mem(); // cancella memerie utente
break;
case 13:
{ if (sciee == false) sciee = true;
else sciee = false;}
break;
case 14:
inputsci(); //EEX
break;
case 15:
// ln
{lastx = regx; regx = log(regx);}
break;
case 16:
// exp e^x
{lastx = regx; regx = exp(regx);}
break;
case 17:
//10alla x
{if (regx < 30)
{lastx = regx; regx = pow(10,regx);}}
break;
case 18:
// disponibile
break;
case 19:
// calcolo fattoriale di x max 30
fact();
break;
case 20:
// da radianti a centesimali
{ lastx = regx; regx = regx*200.0/PI;}
break;
case 21:
// da centesimali a radianti
{ lastx = regx; regx = regx*PI/200.0;}
break;
case 22:
// disponibile
break;
case 23:
// disponibile
break;
case 24:
// disponibile
break;
case 25:
// disponibile
break;
case 26:
// disponibile
break;
case 27:
// disponibile
break;
case 28:
// disponibile
break;
case 29:
// disponibile
break;
case 30:
// disponibile
break;
case 31:
// disponibile
break;
case 32:
// disponibile
break;
case 33:
// disponibile
break;
case 34:
// disponibile
break;
case 35:
// disponibile
break;
case 36:
// disponibile
break;
case 37:
// disponibile
break;
case 38:
// disponibile
break;
case 39:
// disponibile
break;
case 40:
// disponibile
break;
}
} // fine void XEQ
//**********************************************************************************************
//***********************************************************************************************
// ************ per simulare il for *************************************************************
// nella inc1, inc2 ... ecc viene inserito il valore target lo prende da x in fase inserimento
// lo step è fisso uguale ad 1
// la variabile cont viene azzerata in fase di inserimento
// **********
// nella fase di elaborazione con gira == true
// cont viene incrementato di 1 ad ogni passaggio
// il registro x viene salvato in lastx in regx viene posto il cont attuale
// nel registro regy viene posto inc (target)
// a questo punto si può effettuare un controllo x con y ed verificare se il target è raggiunto.
//***********************************************************************************************
void inc_n()
{
int mem = visore;
if (( mem < 1 )||(mem > 6)) return;
switch (mem)
{
case 1:
if (gira == false){inc1 = regx; cont1 = 0;} // nella fase inserimento
else { cont1 = cont1+1; lastx = regx; regx = cont1; regy = inc1; }
// nella fase elaborazione gira = true
break;
case 2:
if (gira == false){inc2 = regx; cont2 = 0;}
else { cont2 = cont2+1; lastx = regx; regx = cont2; regy = inc2; }
break;
case 3:
if (gira == false){inc3 = regx; cont3 = 0;}
else { cont3 = cont3+1; lastx = regx; regx = cont3; regy = inc3; }
break;
case 4:
if (gira == false){inc4 = regx; cont4 = 0;}
else { cont4 = cont4+1; lastx = regx; regx = cont4; regy = inc4; }
break;
case 5:
if (gira == false){inc5 = regx; cont5 = 0;}
else { cont5 = cont5+1; lastx = regx; regx = cont5; regy = inc5; }
break;
case 6:
if (gira == false){inc6 = regx; cont6 = 0;}
else { cont6 = cont6+1; lastx = regx; regx = cont6; regy = inc6; }
break;
}
} // fine void inc_n
//-------------------------------------------------------------------------
void delay_mm()
{
//int mem = visore;
int mem = indirizzo;
if (( mem < 1 )||(mem > 6)) return;
switch (mem)
{
case 1:
{ delay(5);}
break;
case 2:
{ delay(10);}
break;
case 3:
{ delay(50);}
break;
case 4:
{ delay(100);}
break;
{ delay(250);}
case 5:
{ delay(500);}
break;
case 6:
{ delay(1000);}
break;
}
} // fine
//*******************************************************************************
//********************************************************************************
// F I N E L I S T A T O **************************************************
//
//********************************************************************************
Nessun commento:
Posta un commento
Vi ringrazio per la lettura e vi invito al prossimo post.
Se il post vi è stato utile, vi è piaciuto oppure no, scrivete un commento.
Un saluto a tutti.
Sergio
Copyright - Condizioni d’uso - Disclaimer
http://avventurarduino.blogspot.it/2012/10/inizia-lavventura-arduino-12-settembre.html