Nokkiero – telecomando via SMS con un vecchio cellulare Nokia 5110

Telecomando via SMS.
Utilizza un telefonino Nokia 5110 come ricevitore e può controllare fino a 7 relè. La ricezione può essere abilitata con chiamata proveniente da qualsiasi telefonino o solo da uno specifico numero. I comandi inviabili sono 3: ON, OFF e PULSE. Pubblicato a mio nome sulla rivista “Fare Elettronica” (Edizioni Inware) Febbraio 2004 con il titolo “Nokkiero, telecomando via SMS”.
Il file scaricabile gratuitamente nokkiero.zip contiene:
inthebox.jpg – una foto del dispositivo inserito in una scatola
main.s19 – il codice in formato S19 Motorola per programmare il micro
prognote.txt – avvertenza per chi programma un micro OTP
schematic.pdf – lo schema elettrico del circuito in formato PDF
Per i particolari, consultare la rivista.

Remote control via SMS.
Using an old Nokia 5110 GSM phone as receiver and 68HC05 micro, you can control up to 7 relays. The activation can be selected as free (from any calling number) or limited to a specific phone number stored in memory. The commands available are 3: ON, OFF and PULSE. Each command can be directed to relays 1 to 7. It was published by me on the italian magazine “Fare Elettronica” in the Feb 2004 issue.
The freely downloadable file nokkiero.zip contains:
inthebox.jpg – a picture of the circuit placed in a box
main.s19 – the Motorola S19 code needed to burn the micro
prognote.txt – special not for programming an OTP chip
schematic.pdf – the electronic diagram in PDF format
For additional informations, look at the magazine.

Intercettare tastiera IR di Telecom

Questo circuito converte i segnali ricevuti da una tastierina ad infrarossi della Telecom in dati ASCII inviati su una porta seriale RS232 ; l’uscita può essere collegata, per esempio ad una porta seriale di un PC, usando così la tastierina remota come terminale d’ingresso seriale. Il progetto è stato pubblicato a mio nome sulla rivista CQ Elettronica nell’Ottobre 2006 con il titolo “Intercettare la tastierina a infrarossi per SMS di Telecom”. Nella foto sottostante, il circuito montato :

La tastierina Telecom, per l’invio degli SMS da un telefono fisso predisposto all’uso ; è alimentata da tre pile ministilo da 1.5V ed ha una portata utile di diversi metri :

Il file Ottobre06.zip , disponibile per il download, contiene :

– lo schema elettrico
– il master per il circuito stampato in scala 1:1
– il piano di montaggio
– il file HEX per programmare il microcontrollore Z86E04

Per ulteriori particolari, consultare la rivista o la mia pagina delle pubblicazioni.

Allego il sorgente di un file in C, che può essere usato sotto DOS per reindirizzare i caratteri provenienti dalla porta seriale COM2 sul buffer per la tastiera di sistema. Con questo trucco, i caratteri provenienti dal circuito verranno considerati dal PC come se fossero stati premuti sulla vera tastiera di sistema, quella connessa alla porta PS/2 o DIN. Il programma, ovviamente, funziona SOLO sotto DOS, vero DOS, non una finestra DOS di Windows 🙂

#include <dos.h>
#include <conio.h>

const int dbr = 0x2f8;
const int dll = 0x2f8;
const int dlm = 0x2f9;
const int lcr = 0x2fb;
const int mcr = 0x2fc;
const int lsr = 0x2fd;
const int msr = 0x2fe;
const int ien = 0x2f9;

void interrupt (*savold)(void);

void interrupt Sercom2(void)
{
unsigned int far *kbd_buf;
unsigned int k;

    kbd_buf = MK_FP(0x0000, 0x0400);
    k = inportb(lsr);
    k = kbd_buf[0x1c/2];
    kbd_buf[k/2] = inport(dbr);
    k += 2;
    if(k == 0x3e)
        k = 0x1e;
    kbd_buf[0x1c/2] = k;
    outportb(0x20,0x20);
}

void Cominit (unsigned int speed, unsigned int dabit,
              unsigned int stobit, unsigned int parity)
{
int quot;

    disable();
    outportb(0x21, inportb(0x21) & 0xf7);
    quot = (short)(115200 / speed);
    outportb(lcr, 0x80);
    outportb(dll, quot % 256);
    outportb(dlm, quot / 256);
    if(parity > 1)
        parity = 3;
    outportb(lcr, (parity << 3) + ((stobit -1) << 2) + (dabit -5));
    inportb(dbr);
    outportb(mcr, 0x0f); /* set DTR and RTS */
    inportb(mcr);
    outportb(ien, 1);
    savold = getvect(11);
    setvect(11, Sercom2);
    enable();
}

extern unsigned _heaplen = 1024;
extern unsigned _stklen  = 512;

int main(void)
{
    clrscr();
    printf("ROBOTOP 2004\n");
    printf("Serial input COM2 redirect to keyboard buffer.\n");
    Cominit(2400,8,1,0);
    keep(0, (_SS + (_SP/16) - _psp));
    return 0;
}

Html più Php = labirinto interattivo

Ho realizzato, qualche tempo fa per scopi didattici, usando unicamente html e php, un piccolo “labirinto” interattivo che può essere facilmente installato su qualsiasi host (io uso, ovviamente, Altervista) che permetta di far “girare” programmi PHP. Per disegnare le “stanze” con le varie combinazioni di porte e oggetti, ho usato un software 3D dell’Ikea:si chiamava Kitchen Planner, era una versione “free” del 2005, se non sbaglio. Una volta disegnate le varie stanze, ne ho fatto dei files jpg che vengono richiamati a seconda della “mappa” del labirinto, inserita in un file di testo, e della “porta” scelta dall’utente durante l’esplorazione dello “strano edificio”. In qualche stanza ci sono “oggetti” cliccabili, ma non voglio dirvi tutto… Se volete dargli un’occhiata cliccate su questo link e vi troverete sulla pagina di partenza, che vedete qui sotto…

labishot

Midi Expander con scheda audio ISA

139cirpic

Basato su micro PIC18F4320, questo circuito permette di realizzare un piccolo expander MIDI con una scheda audio per bus ISA. Testato su 2 diversi circuiti, dovrebbe funzionare per qualunque scheda compatibile ADLIB (l’indirizzo di I/O DEVE essere 0x388). Il software (in questa prima release) risponde a comandi MIDI sul canale 1. I suoni sono generati per mezzo del sintetizzatore FM presente sul chip della scheda audio. Nelle prossime versioni i preset degli strumenti saranno caricati nella earom del micro, invece che nella memoria programma, in modo da consentire esperimenti per la creazione di timbri personalizzati.
I preset possono essere cambiati tramite MIDI dal numero 1 al 16.
Il file scaricabile ef139.zip contiene lo schema del circuito in formato PDF, il file oggetto .hex per programmare il micro e un programma di prova che permette di verificare su un PC se una scheda audio è compatibile con il circuito. Nota: quest’ultimo programma funziona SOLO in modalità DOS reale, non in una finestra DOS di Windows.

139alimpic

L’alimentazione viene ricavata da due trasformatori a uscita variabile di basso costo, regolati sui 9 Volt (in effetti l’uscita è prossima ai 12V).

Look at this short demo video to see the circuit working. Note that it’s in my personal version of english language 🙂 Sorry for that…

pic-isa-midiexp di robotop

Note: I recently added a zip file called midisrc.zip with all the C files used in this project. The C syntax is not very clean, ‘cause I translated the program from the original one I wrote many years ago in Assembly language for a different microcontroller ; for such reason you can read some “goto” instruction… it’s not elegant for a C program, but was useful for quickly translation from asm. 😉

Based on micro PIC18F4320, this circuit makes possible to realize a small MIDI expander using an old ISA-BUS soundcard. Tested on 2 different cards, it should work for any card ADLIB OPL3 compatible (the I/O address MUST be 0x388). The software (in this first release) responds to MIDI commands on Channel 1. The sounds are generated by the FM synthesizer built in the soundcard. The power is derived from two low-cost wall transformers (see picture) with variable output, set to 9V (the output is close to 12V). In future versions presets instruments will be loaded in the micro earom, rather than in the program memory, to allow experiments to create personalized sounds. The presets can be changed via MIDI ranging from 1 to 16.
The file ef139.zip contains the circuit diagram in PDF format, the object file .HEX to program the micro and a test program to verify on the PC if a soundcard is compatible with my circuit. This program runs ONLY in true DOS mode, not in a Windows DOS session.

Recentemente ho ricevuto alcune email con un argomento interessante: lo sviluppo di un piccolo sintetizzatore sempre partendo dalla base di una scheda audio ISA. Riporto (con alcuni omissis) il carteggio in questione :

Domanda:
Ciao Emilio
grazie per avermi risposto, ho visto il tuo progetto e volevo capire se poteva fare al caso mio, se ho ben capito ci posso collegare una tastiera midi e farla suonare tramite gli sf2 built-in della scheda audio (almeno credo), quindi penso che il pic serva per controllare i suoni nativi della scheda audio, confermami se ho capito bene , in alternativa mi interessava capire cosa ci potrei tirare fuori dal “giocattolino”, inoltre secondo te e’ possibile pensare di usarlo per costruirci attorno un mini synth ??

Risposta:
Ciao Mirco. Il PIC controlla direttamente i generatori FM OPL-3 e non usa altro. In pratica, i timbri vengono “costruiti” modificando i registri del chip audio direttamente. Ovviamente, data la mancanza di ram e di DMA, non è possibile usare la risorsa PCM. Tantissimi anni fa ( TRENTA ! ) progettavo strumenti musicali elettronici e così ho trasportato una parte del lavoro che feci allora con gli integrati Yamaha OPL-2, sui chip (assolutamente compatibili) delle varie schede audio ISA. Anche se gli OPL-3 hanno un operatore in più, io ho usato il subset corrispondente ai vecchi modelli. I timbri, quindi, sono tutti di mia programmazione e corrispondono ai suoni principali (chitarra, violino, tromba, clarino, organo eccetera), ma basta modificare alcune tabelle di look-up per ottenere nuovi timbri. Francamente, però, non credo di avere più la documentazione originale dei chip Yamaha, però penso che una ricerca con Google ti permetterà di trovare qualcosa in giro.
Per il funzionamento, sì; se colleghi una tastiera MIDI muta al mio expander, puoi suonare e cambiare i preset. La polifonia, se ricordo bene, l’ho fatta a sette note. Se ne premi di più (contemporaneamente) la più “vecchia” viene eliminata e sostituita dalla più recente.
In pratica, per costruire un sinth, dovresti aggiungere qualcosa per manipolare i dati nei registri, in modo da creare nuovi timbri con pulsanti o potenziometri. Lo spazio sul micro è abbondante, secondo me la cosa è realizzabile.

Domanda:
Ciao Emilio
Moooolto interessante cio’ che mi scrivi, anche se francamente sono a digiuno da troppo tempo sull’elettronica e in particolare sui PIC, pero’ quello che mi hai descritto mi ha chiarito le idee e mi ha messo altri dubbi, nel senso che mi scrivi che hai programmato il pic per ottenere dei timbri (chitarra, violino ecc), ma come fai a cambiare il timbro nel progestto originale ?? inoltre per creare dei nuovi timbri dovre dovrei agire nel codice ?? e per ultimo per il synth come procederesti ? immagino che si dovrebbe costruire qualcosa di analogico che venga letto dal pic per poi ricodificare i chip della scheda audio. Per la polifonia a 7 note per le mie esigenze basta e avanza 🙂
Ti chiedo tutte queste cose per 2 motivi:
1) costruirmi un expander analogico per una delle mie tastiere (e’ vero che con un pc e un po’ di sw si fa prima, pero’ il fascino di un aggeggino hw home made non ha prezzo)
2) potrebbe essere la base per la tesina dell’ esame di maturita’ per mio figlio (si diploma in informatica e farebbe il connubio elettronica informatica e musica)

Risposta:
Ciao Mirco. La sintesi FM che si utilizza nei vari OPL-2 e OPL-3 di brevetto Yamaha, basati sul lavoro di Chowning sulla generazione di spettri di frequenze complessi, mediante modulazione di frequenza, consiste (da parte del programmatore) nello scrivere alcuni parametri nei registri degli oscillatori. Ovviamente il parametro principale è la frequenza di base, cioè l’altezza della nota. Poi ci sono tanti altri fattori, tipo l’ADSR (attack, decay, sustain, release) per ognuno degli oscillatori, la modulazione di un oscillatore con l’altro e via dicendo. Ovviamente, le combinazioni di questi dati producono una quantità ENORME di effetti sonori, ma poi, alla fine, quelli utilizzabili per suonare davvero, sono giusto una ventina. Ovviamente, se ti piacciono i rumori di astronavi aliene, ne puoi creare a centinaia, ma poi che ci fai ? Ci crei un richiamo per extraterrestri ?
Per quanto riguarda il PIC, è uno dei micro che mi piacciono di meno, però si trova anche dal salumiere (quasi) e costa poco. Io ne avevo presi 5 su ebay (di quelli a 40 pin) in un ozioso pomeriggio di domenica e una volta arrivati ho deciso di utilizzarli per questa idea che mi era venuta in mente qualche tempo prima. Il programma sorgente, però, è tutto scritto in C, quindi si può trasportare su qualsiasi altro micro (con adeguato numero di porte di I/O e di flash e ram) senza grosse difficoltà. I timbri sono scritti su tabelle in flash, quindi diciamo che fanno parte del codice sorgente in C, ma nulla vieta di spostare le tabelle in ram o sulla earom (non volatile) presente su tanti tipi di micro. Una volta messe le tabelle su queste memorie alterabili (la ram o la earom) è possibile variare tutti i parametri e quindi produrre timbri a volontà. Tieni presente che per definire uno “strumento” si usano una ventina di bytes in tutto (non ricordo con precisione, dovrei andare a rileggere il sorgente). Per realizzare un sinth, chiaramente, sarebbe opportuno aggiungere un display LCD e magari 6 pulsanti con le frecce su, giù, destra, sinistra e poi accetta e annulla. Con questa interfaccia utente si fa praticamente tutto…

Domanda:
Quindi se non ho ben capito gli opl-2 e opl-3 probabilmente sono usati anche nella mia yamaha dx7 (fantastico synth)
per i richiami alienti diciamo quasi !!!! l’idea sarebbe quella di costruire sei suoni usati dai rockets i gruppi simili, considera comunque che sarebbe un passatempo per me e un bel voto all’esame per mio figlio, sul fatto che si possono emulate decentemente una ventina di strumenti per me basta e avanza, se poi i suoini gernerati magari li distorci un’attimo tanto meglio, come avrai capito amo molto i suoni vintage e sopratutto le favolose sonorita’ degli organi anni 60/70 ….
un’ultima cosa, mi puoi inviare il sorgente in c del pic ??

Risposta: (qualche tempo dopo)
Bene, ho “riesumato” la cartella del progetto ed ho creato il file scaricabile midisrc.zip che contiene tutti i files in C usati per la creazione del file HEX già allegato in precedenza. Modificando questi files, è possibile ampliare o cambiare del tutto il funzionamento del circuito e quindi, con un po’ di pazienza, realizzare anche il sinth di cui si parlava all’inizio.
E’ da notare che alcuni di questi listati in C sono stati “tradotti” dai miei programmi originali in assembler e quindi presentano, a volte, una sintassi un po’ desueta, come nell’uso dei “goto”; questo, però, mi ha permesso la conversione dall’assembler al C in minor tempo.
Spero che questo lavoro sia utile e sarò lieto di continuare ad aggiungere a questa pagina gli eventuali sviluppi della situazione.

Documenti utili:
Manuale in PDF dei primi chip Yamaha YM2413 (li ho usati !) link
Manuale in PDF dei più recenti chip Yamaha YMF262 link
Manuale in PDF del chip OPTi 82C931 (controller audio ISA) link

Riconoscimento accordi

Tempo fa scrissi un programmino per testare il Visual Basic 2005 Express (gratuito, sembra incredibile, conoscendo il soggetto) di Microsoft ; ora ve lo propongo.
L’applicazione permette di riconoscere la nota fondamentale e il tipo di accordo per una qualsiasi digitazione sulla tastiera di una chitarra. Con i checkbox, a destra, si determinano quante e quali note debbano suonare, mentre i radiobutton sulle “corde” servono per indicare dove le dita faranno pressione.
Per usare una corda libera (non premuta su nessun tasto) utilizzate il primo radiobutton a sinistra ; il tipo di accordo e la nota fondamentale possono sembrare, in qualche caso, errati (per esempio Am7 verrà indicato come C6), ma le note di entrambi gli accordi sono esattamente uguali ; si tratta solo di un diverso “punto di vista”… Per una maggiore precisione si dovrebbe conoscere l’accordo precedente, in modo da estrapolare un collegamento armonico, ma questo programma non ha uno “stato precedente”, quindi tenetevelo così com’è 🙂
I tipi di accordi riconosciuti sono 13, tra questi maggiori, minori, seste, settime, aumentate, diminuite eccetera. Se il tipo di accordo risulta “boh!”, cioè non riconosciuto, provate ad eliminare qualcuna delle note attive mediante i checkbox a destra.
Il programma, quando si clicca il pulsante “play”, suona l’accordo con lo strumento MIDI n.25, che è la chitarra. Ovviamente è necessario che sul PC sia installata una scheda audio in grado di riprodurre files MIDI… e che il volume non sia azzerato 🙂  Il file di installazione può essere prelevato da questo link.
Nota importante : sul PC deve essere installato il framework .NET ; se non avete un computer a legna e carbone, probabilmente è già presente 😉
Nell’immagine in basso è visibile uno “screenshot” del programma in funzione…

chordrec

FreeBASIC – Esercizi

Steganografia
Vi propongo un altro esercizio per il FreeBASIC. Si tratta di un programmino scritto da me che consente di leggere un messaggio “nascosto” in una immagine. Il file immagine che contiene il messaggio è questo qui sotto:

foto con messaggio nascosto :)

Si tratta, come vedete, di una immagine in formato BMP con 256 toni di grigio. L’utilizzo di questo formato è dettato dalla semplicità di decodifica di tale tipo di file. Invito chiunque fosse interessato (basta fare una ricerca su Google) a studiare cosa c’è scritto nell’intestazione (lo header) di un file .BMP ; non è per niente complicato.
Bene: come possiamo “nascondere” un testo in una fotografia ? Semplice… ogni pixel di una foto in formato BMP a 256 toni di grigi è un byte che può avere un valore da 0 a 255 ; lo zero rappresenta il nero totale, il 255 invece è il bianco pieno. Tutti i valori intermedi sono i vari livelli di grigio. Allora noi che facciamo ? prendiamo il bit meno significativo di ognuno di questi bytes e lo modifichiamo per comporre una sfilza di bits che saranno il nostro messaggio testuale “nascosto”. Cambiare il colore di un pixel da 255 a 254, per esempio, risulterà totalmente invisibile all’occhio umano, perché si passerà da un bianco pieno a un bianco appena un po’ meno pieno. Lo stesso dicasi di un pixel che aveva valore 000 (tutto nero) e passa a 001 (appena un po’ meno nero). L’occhio non percepisce queste piccole differenze, specie perché è attirato dalla visione “globale” della fotografia.
Vi propongo il listato del programma sorgente in FreeBASIC che esegue il lavoro di decodifica. Appena lo avrete compilato, mandatelo in esecuzione e vi troverete un nuovo file di testo, chiamato epgficara.txt, contenente un mio breve curriculum vitae. Nota importante: mettete nella stessa cartella il programma che compilerete e il file immagine epgficara.bmp che potrete scaricare da questa pagina cliccando con il tasto destro e facendo “salva con nome” e assicuratevi che la cartella in cui mettete le cose sia provvista dei diritti di scrittura, altrimenti il programma non potrà produrre il file di testo in uscita.
Ecco, quindi, il file sorgente per FreeBASIC:

dim shared as string nfi, a
dim shared as long start, leng, fl
dim shared as ubyte db, src

print "Decodifica steganografia in file BMP - 256 livelli grigio - V13.0316 - (c)2013 Emilio P.G. Ficara"
nfi = "epgficara.bmp" ' nome del file da decodificare
If Dir(nfi) = "" then
  Print "Errore: il file ";nfi;" non esiste"
  Goto exits
EndIf

Open nfi for binary as #1 ' apri il file da leggere
a = Input$(54,#1) ' leggi solo l'intestazione (header)
If Left(a, 2) <> (Chr(&h42) + Chr(&h4d)) then ' se errato il "magic number"
  Print "Errore: non è un file BMP"
  Goto exits
EndIf
If Mid(a,&h1C+1,2) <> (Chr(8)+Chr(0)) then ' se non è 8 bit per pixel
  Print "Errore: non è 8 bit per pixel"
  Goto exits
EndIf
If Mid(a,&H1E+1,4) <> (Chr(00)+Chr(00)+Chr(00)+Chr(00)) then ' se è compresso
  Print "Errore: è compresso RLE-8 o RLE-4"
  Goto exits
EndIf
If Mid$(a,&H2E+1,4) <> (Chr(00)+Chr(01)+Chr(00)+Chr(00)) then ' se non è 256 toni di grigio
  Print "Errore: non è 256 toni di grigio"
  Goto exits
EndIf

start = Asc(Mid(a,&H0a+1,1)) ' calcola l'indirizzo di inizio del primo pixel d'immagine
start = start + Asc(Mid(a,&H0b+1,1))*&H100
start = start + Asc(Mid(a,&H0c+1,1))*&H10000
start = start + Asc(Mid(a,&H0d+1,1))*&H1000000

leng = Asc(Mid(a,&H22+1,1)) ' calcola lunghezza in bytes dell'immagine
leng = leng + Asc(Mid(a,&H23+1,1))*&H100
leng = leng + Asc(Mid(a,&H24+1,1))*&H10000
leng = leng + Asc(Mid(a,&H25+1,1))*&H1000000

Open "epgficara.txt" for output as #9 ' apri file di uscita (testo)

fl = 54 ' salta la tabella dei colori
While fl < start
  get #1,,src ' leggi un pixel (un byte) del file BMP
  fl = fl+1
Wend

fl = 0 ' contatore dei bytes in input
db = 0 ' byte ricomposto dai singoli bits (inizialmente a 0)
While fl < leng
  If (fl > 0) And ((fl and 7) = 0) then ' per 8 bytes di immagine (excludendo il primo)
    Print #9, Chr(db); ' scrivi un carattere sul file di output (testo)
    db = 0 ' azzera il byte per la ricomposizione dei bits
  EndIf

  get #1,,src ' leggi un pixel (un byte) dal file BMP
  If (src and &H01) then ' se il nostro bit nascosto è 1
    db = db Or (2 ^ (fl and 7)) ' metti a 1 il relativo bit nel byte ricomposto
  EndIf
  If db = &Hff then exit while ' se trovo la combinazione &HFF (8 volte 1), il testo è finito
  fl = fl + 1 ' altrimenti incremento il numero di bytes letti
Wend

exits:
close ' chiudi tutti i files aperti
End

P.S. se qualcuno preferisse avere il programma già compilato e pronto per essere eseguito, potrà scaricare il file stegodec.zip , decomprimerlo in una qualsiasi cartella, aggiungere -come detto prima- il file BMP da decrittare e lanciare l’eseguibile. Non è richiesta alcuna installazione, non viene modificata nessuna voce di registro.

Don’t waste energy !

Sometimes you need to fully discharge your tablet’s battery, ‘cause you must drain all the power to obtain an Hardware Reset that can make your tablet able to restart with the upgrade process. So, I have used this simple technique to speed-up the process and to NOT WASTE energy !
I simply attached a USB battery charger to the tablet’s expander board, so while the tablet’s battery fastly discharges, my AA Ni-Mh charges 😉

dumper

FreeBASIC – esercizi

Permutazioni semplici e soluzione esercizio Bocconi

Eccomi di nuovo a voi con un programmino in FreeBASIC. L’occasione per scriverlo è capitata ieri, quando mi è stato presentato un problema di “allenamento” per le gare internazionali di matematica organizzate dall’università Bocconi. Questi “allenamenti” sono basati su esercizi dati in passato per altre gare dello stesso tipo; in particolare, questo che vi propongo si trovava in una gara del 2006. Potete prelevare il file PDF da questo link che ho trovato su internet. Nel documento PDF ci sono diversi esercizi, ma quello che mi è stato proposto è il numero 10, denominato CONNESSIONE. Devo dire che la parte più difficile della soluzione è stata quella di interpretrare la traccia che, francamente, era parecchio oscura e talvolta rasentava la mancanza di senso, come nella frase “la somma, magari costituita da un unico addendo”, ma una volta capito quello che veniva inteso, il resto è stato facile.
Con un po’ di ragionamenti (partendo dalle somme 1 e 2) si trova facilmente la soluzione, anzi una delle soluzioni possibili. E questo basta per dire di aver risolto il problema. Ok. Dopo un po’ ho pensato di realizzare un programma che trovasse, matematicamente, tutte le possibili soluzioni. Ho impostato la traccia in un modo diverso, che a me è sembrato più chiaro. Ho immaginato sette villette disposte in un certo territorio. Ogni villetta ha il proprio numero civico, da 1 a 7. Da ogni villetta si scorgono una o più delle altre (alcune non sono reciprocamente visibili) e le persone che vivono in ognuna di esse, decidono di calcolare la somma dei numeri civici delle villette che riescono a vedere. I risultati di 6 di questi personaggi sono noti (1, 2, 3, 5, 8, 13), si chiede quale sia la somma calcolata dal settimo. Ho realizzato uno schemino per spiegare queste relazioni:

casette

Sa = B
Sb = A + C + F
Sc = B + D
Sd = C + E + F + G
Se = D
Sf = B + D + G
Sg = D + F

Per ‘Sa’ si intende la somma dei numeri civici delle villette viste dall’abitazione [ a ], per ‘Sb’ quelli visti dalla villetta [ b ] e così via. In pratica le linee che collegano le casette indicano la possibilità di “vedere” le altre. Il programma, quindi, agisce così: genera tutte le possibili PERMUTAZIONI SEMPLICI di 7 elementi, calcola le equazioni per ognuna delle permutazioni e verifica nei risultati se 6 di essi corrispondono a quelli dati nella traccia ; in quel caso, rivela il settimo che è la soluzione. Le permutazioni di 7 elementi sono 5040 (corrispondenti a 7 fattoriale), ma le soluzioni sono solo 8, delle quali 4 non valide perché alcune delle somme si ripetono. Le restanti 4 danno come totale 22, 21 o 19 (quest’ultimo in due permutazioni), che sono quelle indicate come risultato dalla Bocconi.
Le permutazioni vengono tutte salvate sul file di uscita risultati.txt e dopo ogni riga valida, cioè che risponde ai requisiti, viene stampato un ‘*** Ok’ seguito dalle somma calcolate da tutti gli “abitanti” delle villette, da ‘Sa’ a ‘Sg’. Di sotto, il listato del programma :

Dim Shared As Integer contatore(7) ' array usato come contatore a 7 digit
Dim Shared As Integer civici(7) ' array dei numeri civici
Dim Shared As Integer somme(6) ' array delle somme gia' note
Dim Shared As Integer nrow ' numero riga per stampa
Dim Shared As Integer finito ' segnalatore di iterazioni finite

' subroutine per creazione nuova permutazione semplice
'-----------------------------------------------------
Sub Newrow()
Dim As Integer x,y

retry:
    x = 7 ' posiziona su elemento piu' a destra del contatore
    Do
        contatore(x) = contatore(x) +1 ' passa a nuovo digit
        If contatore(x) <= 7 Then Exit Do ' termina se non li hai usati tutti
        contatore(x) = 1 ' altrimenti ricomincia dal primo digit
        x = x -1 ' passa al digit immediatamente a sinistra
    Loop Until x = 0 ' esegui per tutti i digits
    If x = 0 Then ' se il conteggio è finito (tutti i digits usati)
        finito = 1 ' attiva segnale di conteggio terminato
        Exit Sub ' termina la subroutine
    Endif 

    ' vogliamo le permutazioni semplici, quindi saltiamo
    '  le combinazioni con elementi ripetuti
    For x = 1 to 6
        For y = x+1 to 7
            If contatore(x) = contatore(y) Then Goto retry
        Next y
    Next x
End Sub

' subroutine per la stampa della attuale permutazione
'----------------------------------------------------
Sub Outrow()
Dim As Integer x

    Print #1,nrow, ' scrivi nuova riga permutazione semplice
    nrow = nrow +1
    For x = 1 to 7
        Print #1, civici(contatore(x));" ";
    Next x
    Print #1, ' fine linea

End Sub

' subroutine per il calcolo del problema
'---------------------------------------
Sub Calcola()
Dim As Integer S(7)
Dim As Integer x, y, num

    ' calcolo somme numeri civici visibili da ogni villetta
    S(1) = civici(contatore(2)) ' Sa = b
    S(2) = civici(contatore(1)) + civici(contatore(3)) + civici(contatore(6)) ' Sb = a+c+f
    S(3) = civici(contatore(2)) + civici(contatore(4)) ' Sc = b+d
    S(4) = civici(contatore(3)) + civici(contatore(5)) + civici(contatore(6)) + civici(contatore(7)) ' Sd = c+e+f+g
    S(5) = civici(contatore(4)) ' Se = d
    S(6) = civici(contatore(2)) + civici(contatore(4)) + civici(contatore(7)) ' Sf = b+d+g
    S(7) = civici(contatore(4)) + civici(contatore(6)) ' Sg = d+f

    num = 0 ' azzera numero di somme valide
    For x = 1 to 7 ' per tutte le somme calcolate
        For y = 1 to 6 ' per tutte le somme gia' note
            If S(x) = somme(y) then
                num = num +1
                y = 6 ' termina il for interno
            Endif
        Next y
    Next x
    If num = 6 Then ' tutti le somme valide
        Print #1,"*** ok ";
        For x = 1 to 7
            Print #1, "[";S(x);"] ";
        Next x
        Print #1,
    Endif
End Sub

' programma principale
'---------------------

    Print " **********************************************************"
    Print " ** Programma per il calcolo della soluzione al problema **"
    Print " **  delle sette casette con numeri civici da 1 a 7, che **"
    Print " **  si vedono nella mappa allegata al problema.         **"
    Print " ** Compilato con FreeBasic, opzione QB - E.Ficara 2011  **"
    Print " **********************************************************"

    civici(1) = 1: civici(2) = 2: civici(3) = 3: civici(4) = 4 ' assegna numeri civici alle casette
    civici(5) = 5: civici(6) = 6: civici(7) = 7

    somme(1) = 1: somme(2) = 2: somme(3) = 3 ' assegna le somme gia' note
    somme(4) = 5: somme(5) = 8: somme(6) = 13

    For i = 1 to 6 ' inizializza contatore 7 digit
        contatore(i) = 1
    Next i
    contatore(i) = 0 ' combinazione -1 (per successivo incremento con Newrow)

    nrow = 1 ' inizializza numero linea per stampa
    finito = 0 ' inizializza il segnalatore di iterazioni complete

    Open "risultati.txt" For Output As #1 ' prepara file di uscita
    Print #1,"Permutazioni semplici:" & Chr$(13) & Chr$(10)
    Do ' inizia loop combinazioni
        Newrow ' calcola nuova permutazione semplice
        If finito > 0 then Exit Do ' esci se segnale di conteggio finito 
        Outrow ' altrimenti stampa linea
        Calcola ' esegui calcolo del problema
    Loop
    Close #1

    Print "Programma terminato. E' stato creato il file risultati.txt"
    Print "Premere un tasto qualsiasi per terminare..."
    Do
        If Inkey$ <> "" then Exit Do
    Loop
End

FreeBASIC – esercizi

Senti, ma… come lo facevano i Babilonesi ?

Sebbene il titolo possa dar adito a sospetti sull’argomento trattato, quello che vi propongo è solo un altro piccolo esempio di utilizzo del FreeBASIC. Mi sono trovato a dover fare dei calcoli con le radici quadrate in un progetto su un microcontrollore. I microcontrollori NON hanno la possibilità di eseguire calcoli di questo tipo, diciamo che in genere possono fare (in modo primitivo, cioè senza scrivere un programma apposito) addizioni, sottrazioni, moltiplicazioni e divisioni per multipli di 2 (istruzioni di shift a sinistra e a destra), ma non è questo l’argomento che ci interessa.

Insomma, trovandomi a dover fare una radice quadrata senza avere una istruzione adeguata (intendo istruzione del microcontrollore, non la mia !!!) , mi sono ricordato di un metodo con iterazioni successive che si dice sia stato inventato dai Babilonesi. Ora io, con quattromila anni di ritardo, l’ho provato con un programmino facile-facile in FreeBasic, prima di trasportare lo stesso algoritmo sul microcontrollore. Ovviamente, questo listato che vi propongo può lavorare anche con numeri con la virgola, mentre quello che adotterò sul microcontrollore potrà lavorare solo su numeri interi. Ecco il listato:

' programma principale
'---------------------

    Print " **********************************************************"
    Print " ** Programma per il calcolo della radice quadrata di un **"
    Print " **  numero con il metodo BABILONESE.                    **"
    Print " ** Compilato con FreeBasic, opzione QB - E.Ficara 2011  **"
    Print " **********************************************************"
    Do
        Print: Print "Nota: i numeri decimali vanno inseriti con il punto, non la virgola.": print
        Input "Numero di cui si vuol calcolare la radice quadrata (0 per finire) "; num
        If num < 0 Then
            Print "La radice quadrata di un numero negativo ? Non la so fare... e tu ?"
            Print " - dai, ti cambio il segno..."
            num = -num ' ecco fatto
        Endif
        If num = 0 Then Exit Do ' termina se l'utente ha inserito 0 
        prec = 0.01 ' precisione 0.01 (due cifre decimali); modificare se serve
        sq = 1 ' inizializza risultato con numero arbitrario
        old = num ' metti al massimo possibile il valore iterazione precedente 
        Do ' loop iterazioni
            sq = (sq + num / sq) / 2 ' calcola nuova iterazione
            If (old-sq) < prec Then Exit Do ' se la precisione è raggiunta, termina loop
            old = sq ' altrimenti aggiorna valore precedente
            Print "... iterazione: "; sq
        Loop
        Print "risultato: ";sq
    Loop
End

FreeBASIC – esercizi

Voglio proporvi uno strumento utile per lo sviluppo di semplici programmi in ambito matematico e non solo. Si tratta del FreeBASIC, un compilatore Basic gratuito ed open-source che funziona molto bene ed ha il grosso pregio di poter compilare anche i vecchi listati di QBasic e GW Basic che erano (un tempo) usatissimi e con i quali sono state sviluppate migliaia di applicazioni, matematiche, scientifiche e anche ludiche (i primi videogames). Io l’ho installato sul mio portatile con Win7 Home Edition e funziona a meraviglia, ma esiste anche in ambiente LINUX ed ha esattamente le stesse caratteristiche. Nella colonna a destra, sotto ‘links utili’, trovate il collegamento al sito per il download.

Calcolo numeri primi

Un paio d’anni fa mi fu proposto di risolvere un problema scolastico nel quale si chiedeva l’elenco dei numeri primi (fino a 2000) che avessero queste caratteristiche:
a) avere differenza 10 col numero primo che lo precedeva
b) avere tutte le cifre diverse

Risolsi il problema scrivendo un piccolo programmino con il GFW-Basic (un vecchio compilatore a 16 bit per Windows, molto efficiente) ed ora, con minime modifiche, l’ho ricompilato con FreeBASIC e l’ho fatto girare su Win7 (in una finestra DOS) ; funziona perfettamente. Ve lo propongo in forma di listato in modo che possiate provare a compilarlo voi stessi, una volta installato il FreeBASIC. Aggiungo il contenuto del file compila.bat che uso per creare l’eseguibile:

C:\FreeBASIC\fbc.exe -lang qb primi.bas
pause

Naturalmente, questo prevede che il FreeBASIC sia stato installato nella directory C:\FreeBASIC e che al listato abbiate dato il nome primi.bas. Se il compilatore è stato installato in una diversa directory o il nome del file sorgente è diverso, modificate il batch di conseguenza.

Ecco il listato del file sorgente primi.bas :

Dim primi(2000) ' buffer per numeri primi
Dim diff(2000) ' buffer per differenze

    Print " *********************************************************"
    Print " ** Programma per il calcolo dei numeri primi e delle   **"
    Print " **  differenze tra un numero primo e il precedente.    **"
    Print " ** Compilato con FreeBasic, opzione QB - E.Ficara 2011 **"
    Print " *********************************************************"

    primi(1) = 2 ' il primo numero primo (escludendo 1)
    diff(1) = 1 ' la prima differenza
    last = 2 ' indice iniziale dell'ultimo numero primo calcolato
    For i = 2 To 2000 ' limita la ricerca al numero 2000; modificare se serve
        For j = 1 To last - 1 ' prova divisibilita' con numeri precedenti
            If (i / primi(j)) = Int(i / primi(j)) Then Exit For ' esci se divisione intera
        Next j
        If j = last Then ' se non ha trovato divisori (e' un numero primo)
            ' NOTA: le prossime istruzioni servono per ESCLUDERE dalla lista dei numeri primi
            '       quelli che contengono cifre uguali (11 per esempio)
            m = 1110 ' inizializza valore migliaia (arbitrario) <> centinaia e decine
            c = 100 ' inizializza valore centinaia (arbitrario)
            d = 110 ' inizializza valore decine (arbitrario) <> centinaia
            u = i ' inizializza unita' con il numero in esame 
            If u >= 1000 Then ' se maggiore o uguale a 1000
                m = Int(u / 1000) ' m contiene le migliaia
                u = u - m * 1000 ' u contiene il resto (0-999)
            EndIf
            If u >= 100 Then ' se maggiore o uguale a 100
                c = Int(u / 100) ' c contiene le centinaia
                u = u - c * 100 ' u contiene il resto (0-99)
            EndIf
            If u >= 10 Then ' se maggiore o uguale a 10
                d = Int(u / 10) ' d contiene le decine
                u = u - d * 10 ' u contiene il resto (0-9)
            EndIf
            ' per mettere in lista tutti i numeri primi, sostituire la prossima linea
            ' con    If (1) Then    o eliminarla insieme al suo EndIf
            If m <> c And m <> d And m <> u And c <> d And c <> u And d <> u Then ' se m,c,d e u sono diversi
                primi(last) = i ' salva il numero in esame tra i primi
                diff(last) = i - primi(last - 1) ' calcola e salva la differenza col precedente
                last = last + 1 ' incrementa indice dell'ultimo numero calcolato
            EndIf
        EndIf
    Next i

    Open "primi.txt" For Output As #1 ' prepara file di uscita
    Print #1," 1", " 0" ' scrivi il primo numero primo :-)
    For i = 1 To last - 1 ' scrivi tabella numeri primi e differenze
        Print #1,primi(i), diff(i)
    Next i

    Print #1, ' interlinea

    ' scrivi tabella dei numeri primi che hanno differenza 10 col precedente
    For i = 1 To last - 1
        If diff(i) = 10 then
            Print #1,primi(i), diff(i), primi(i - 1)
        EndIf
    Next i
    Close #1

    Print "Programma terminato. E' stato creato il file primi.txt"
    Print "Premere un tasto qualsiasi per terminare..."
    Do
        if Inkey$ <> "" then Exit Do
    Loop

Il programma genera un file di uscita chiamato primi.txt nel quale sono elencati i numeri primi (eccetto quelli che hanno cifre uguali, tipo l’ 11 per intenderci) e, dopo questi, la lista dei numeri primi che hanno differenza 10 con il precedente (nel limite di 2000 posto come massimo per l’indagine).