MAME e Outputs: Guida Pratica

« Older   Newer »
 
  Share  
.
  1.  
    .
    Avatar

    appassionato
    Amministratore

    Group
    Fondatore Supremo
    Posts
    167

    Status
    Offline
    INTRODUZIONE
    Con questa guida cercherò di fare un po’ di chiarezza su cosa siano e soprattutto su come possano essere gestiti gli outputs in MAME.
    Nei cab dedicati, onestamente, sono pochi i casi in cui gli outputs sono veramente necessari (mi viene in mente il knocker di Q*bert, il "rinculo" delle pistole di alcuni giochi e poco altro…); completamente diverso il caso dei cabinati di guida: luci ed effetti al volante (rumble se non addirittura Force Feedback in alcuni casi) sono parte integrante dell’ esperienza di gioco, si pensi al tasto start lampeggiante che SEGA ha introdotto in tutti i suoi cab da outrun in poi, i lampeggianti in chase HQ, etc etc.

    Ad oggi non esistono prodotti commerciali economici per far fronte al “problema”: per le luci esistono periferiche tipo LedWiz e SmartASD, mentre per il rumble… praticamente niente (forse la smartASD è configurabile per il rumble, ma costa 20 volte tanto).
    MAME supporta gli output da parecchio tempo, tipo dalla versione 0.110; questi output, propri delle schede emulate, non possono essere utilizzati direttamente per il semplice fatto che MAME non li indirizza su alcuna periferica del PC. La cosa non deve sorprendere più di tanto dal momento che sarebbe codice che esula dallo scopo del MAME stesso. A questo fine ci viene in aiuto un software a mio avviso geniale, scritto da Howard Casto, utente molto attivo sul forum BYOAC. Questo software si prende la briga di “leggere” i mistici messaggi di output di MAME e di “tradurli” in formati digeribili da hardware esterni. Questi formati sono vari ed eventuali, ma a noi interessa la sola comunicazione seriale. Perché? Beh, guarda un po’, le nostre amate schede a microcontrollore Arduino sono in grado, se opportunamente programmate, di leggere questo tipo di segnale e renderlo un segnale logico sfruttabile per controllare altro hardware!
    Ok, ma qual è lo schema complessivo necessario per trasformare questi segnali di output intimamente nascosti in MAME nell’accensione di un LED oppure nel movimento di un motore? Ecco lo schema a blocchi…

    schema_a_blocchi



    In sostanza: MAMEhooker traduce i messaggi di output di MAME rendendoli digeribili da Arduino (o altro hardware); Arduino a sua volta aziona dei driver di potenza (dispositivi cioè in grado di generare correnti anche significative) che accendono LED cicciotti, mettono in movimento motori, etc etc, tutto secondo le volontà di MAME (o, in altre parole, della scheda gioco emulata… mica cazzi!).
    Ciò che questa guida copre è sia la filiera MAME -> MAMEhooker -> Arduino, sia una introduzione all'uso di driverboard per pilotare motori DC, LED grandi e piccoli, lampadine. I pin di arduino infatti possono erogare solo poche decine di mA di corrente, di conseguenza è impensabile controllare direttamente hardware poco più grande di un mini LED.

    Andiamo a vedere come si configurano mamehooker e arduino per avere dei segnali logici “utili” a costo praticamente zero (che ci tengo ;) )!!

    MAME E ARDUINO SETUP
    Innanzitutto scegliamo la “giusta” versione di MAME: la più recente che il tuo sistema riesca a far girare. Questo perchè gli outputs sono una delle ultime cose che sono state inserite nel codice, e ancora oggi ne vengono introdotti con una certa frequenza. In caso dovessi ripiegare su versioni più datate, tieni presente che in alcune versioni di MAME gli output sono buggati e non utilizzabili o addirittura non presenti; meglio dunque evitare le versioni da 0.170 a 0.175 incluse e le versioni prima della 0.110.
    Nel caso il file mame.ini della versione che stai utilizzando avesse la voce “output” sotto “OSD OUTPUT OPTIONS”, questa va settata a “windows”, cioè:


    #
    # OSD OTPUT OPTIONS
    #
    output windows


    Ora sporchiamoci un po’ le mani! Assicuriamoci di riuscire a far girare il giochillo che ci interessa in MAME. Per convenienza futura, meglio mettere la cartella “mame” in un percorso semplice, tipo C:\MAME.
    Colleghiamo la scheda microcontrollore e vediamo se win installa i driver. In caso di uso di un clone con chip CH340 sicuramente non lo installerà. Allego qui i driver del fornitore ufficiale del chip di comunicazione seriale che non si sa mai ;)

    Apriamo l’IDE di arduino. Scegliamo sotto il menù “strumenti” il tipo di scheda (nel mio caso una nano ATMega168) e la porta di comunicazione (nel mio caso COM4, ma potrebbe essere un’altra).
    In caso la tua arduino non venisse riconosciuta cambia porta USB (questa banale operazione mi ha risolto il problema su due diversi PC con win10).
    Carichiamo lo sketch sulla nostra schedina arduino. Il firmware/sketch legge i messaggi in arrivo sulla porta seriale, li interpreta e porta a stato logico alto o basso i corrispondenti pin.


    /*
    Arduino - Mamehooker outputs read setup sketch

    This sketch lets Arduino read outputs signals from
    Howard Casto's Mamehooker.
    Pins from #2 to #13 are set to outputs and can be used
    to send hardware outputs signals.
    Here is an example of mamehooker .ini code
    (message sent to Arduino serial port COM4):

    [General]
    MameStart=cmo 4 baud=9600_parity=N_data=8_stop=1
    MameStop=cmc 4
    StateChange=
    OnRotate=
    OnPause=
    [KeyStates]
    RefreshTime=
    [Output]
    lamp0=
    lamp1=cmw 4 3., cmw 4 %s%, cmw 4 x
    lamp2=cmw 4 4., cmw 4 %s%, cmw 4 x
    lamp3=cmw 4 5., cmw 4 %s%, cmw 4 x
    lamp4=cmw 4 6., cmw 4 %s%, cmw 4 x
    lamp5=cmw 4 7., cmw 4 %s%, cmw 4 x
    lamp6=cmw 4 8., cmw 4 %s%, cmw 4 x
    lamp7=cmw 4 9., cmw 4 %s%, cmw 4 x
    lamp8=cmw 4 10., cmw 4 %s%, cmw 4 x
    lamp9=cmw 4 11., cmw 4 %s%, cmw 4 x
    lamp10=cmw 4 12., cmw 4 %s%, cmw 4 x
    lamp11=cmw 4 13., cmw 4 %s%, cmw 4 x

    Code adapted from fruit-emu.com (majoris and eric)

    by Barito, 2018
    */

    int pin;
    int value;

    void setup() {
    pinMode(2, OUTPUT);
    pinMode(3, OUTPUT);
    pinMode(4, OUTPUT);
    pinMode(5, OUTPUT);
    pinMode(6, OUTPUT);
    pinMode(7, OUTPUT);
    pinMode(8, OUTPUT);
    pinMode(9, OUTPUT);
    pinMode(10, OUTPUT);
    pinMode(11, OUTPUT);
    pinMode(12, OUTPUT);
    pinMode(13, OUTPUT);

    Serial.begin(9600);
    }

    void loop(){
    while (Serial.available()>0){
    pin = Serial.parseInt();
    value = Serial.parseInt();
    if (Serial.read() == 'x'){
    digitalWrite(pin, value);
    }
    }
    }


    Nello sketch sono impostati come outputs tutti i pin dal numero 2 al 13. Volendo si potrebbero aggiungere i pin “analogici” (o meglio, capaci di ricevere input analogici) per un totale di 20 outputs, più che sufficienti per qualsiasi giochillo arcade!
    Bene, l’hardware base necessario a testare le funzionalità di mamehooker è pronto.

    MAMEHOOKER SETUP
    Scompattiamo mamehooker (alla versione 5.1 nel momento in cui scrivo) e mettiamolo in C:\.
    Entriamo nella cartella di mamehooker e lanciamo l’eseguibile “mamehook.exe” (se al primo avvio ritorna errori di file mancanti, lancialo come amministratore.). Comparirà una iconcina in basso a destra della barra di win. La clicchiamo e si aprirà la debug window di mamehooker. Impostiamo in mamehooker il percorso in cui abbiamo messo mame nel menù a tendina “options”, voce “Set MAME path for Driver/Parent Detection”.

    png



    Va indicato il percorso completo, escluso il nome dell’eseguibile. Subito dopo ci verrà chiesto di indicare il nome dell’eseguibile (es. mame.exe).
    Bene! Mamehooker è agganciato a MAME!
    Ora lanciamo il gioco di cui vogliamo mappare gli outputs. Io ho scelto outrunners perché (a) ha un sacco di outputs, (b) è fra i miei giochi preferiti di sempre. Se mamehooker è collegato correttamente comincerà, via via che si avanza nelle schermate, a riconoscere gli outputs del gioco. Sentirai un “bing” ad ogni riconoscimento.
    Questa la schermata di log che ho ottenuto io dopo il lancio e dopo essere arrivato al “via” della corsa.

    png



    Adesso andiamo nella cartella di mamehooker, apriamo la cartella “ini”, “MAME, e apriamo il file ini del gioco che stiamo configurando (nel mio caso orunners.ini). Qui dobbiamo impostare le azioni che mamehooker dovrà eseguire quando MAME gli manderà un segnale di output. Il file “orunners.ini” diventa una cosa di questo tipo:


    [General]
    MameStart=cmo 4 baud=9600_parity=N_data=8_stop=1
    MameStop=cmc 4
    StateChange=
    OnRotate=
    OnPause=
    [KeyStates]
    RefreshTime=
    [Output]
    MA_Check_Point_lamp=cmw 4 2., cmw 4 %s%, cmw 4 x
    MA_Race_Leader_lamp=cmw 4 3., cmw 4 %s%, cmw 4 x
    MA_Steering_Wheel_motor=
    MA_DJ_Music_lamp=
    MA_<<_>>_lamp=
    MB_Check_Point_lamp=
    MB_Race_Leader_lamp=
    MB_Steering_Wheel_motor=
    MB_DJ_Music_lamp=
    MB_<<_>>_lamp=


    Dove:
    la prima linea dopo “MameStart=” stabilisce la connessione seriale e le sue caratteristiche
    “cmw” è il comando di scrittura su porta seriale di mamehoker
    “4” è la porta seriale di trasmissione (COM4)
    “2.” e 3.” sono i pin di arduino che controllano le due lampade in parola (il punto è un delimitante che serve ad arduino per capire che si tratta del pin da utilizzare)
    “%s%” indica lo stato attuale della lampada (accesa o spenta, dato fornito da MAME, o meglio dalla scheda che emula)
    “x” dice ad arduino che il messaggio è terminato.
    Io qui ho settato solo le lampade di check point perché vengono usate anche durante l’attract mode e possiamo verificare subito se funziona, senza nemmeno inserire crediti.
    Nota: arrivare a questo file passando dal menu a tendina “Script Editor” e scegliendo “Edit INI For Current Rom”, come suggerirebbe la guida ufficiale di Howard, a me con win 7 restituiva un errore di runtime. Se non ricordo male con winXP questo problema non c’era. Se riesci ad utilizzare lo script editor è meglio perché ti mostra tutti i comandi supportati da mamehooker e le opzioni disponibili.
    Ora chiudiamo mamehooker e riavviamolo. Lanciamo il giochillo che abbiamo configurato et voilà, i nostri outputs sono pronti per essere utilizzati!!

    VIDEO!
    Nel video di seguito lancio outrunners da riga di comando e subito due LED collegati (brutalmente) ai pin “2” e “3” di una arduino nano iniziano a lampeggiare controllati dal giochillo… poco fico!? :D

    www.youtube.com/embed/V5D2I7cC_1A?ecver=2

    Passiamo alle driver board e periferiche.

    ATTENZIONE – giocare con l’elettricità può essere molto pericoloso! Molti dei componenti di seguito descritti possono diventare molto caldi in esercizio. L’uso di alimentatori non adeguati può provocare incendi e danni a persone e cose. Non mi riterrò responsabile di danni a persone o cose che le informazioni di seguito riportate o un uso errato di esse possano provocare.

    Le soluzioni qui proposte non sono necessariamente lo stato dell’arte quindi consiglio, in ogni caso, di fare una ricerca in rete prima di acquistare componenti o adottare una delle soluzioni qui suggerite.

    ESEMPIO 1 – LED A BASSA POTENZA E CLASSICA LAMPADINA A INCANDESCENZA 5V DA CAB
    In caso di LED a bassa potenza, tipo quelli montati sui tasti arcade "di nuova generazione" con i quali spesso vedo le plance dei cab trasformate in luminarie natalizie, possiamo realizzare un semplice switch con un transistor NPN tipo BC547.

    npn_switch



    Il transistor ha le seguenti caratteristiche:

    Tensione di controllo: 5V DC
    Tensione di alimentazione: 5-40V DC
    Corrente massima erogabile: 100 mA


    La resistenza alla base viene inserita per ridurre la corrente chiesta ad Arduino per mandare in saturazione la base stessa ed attivare lo "switch". Nota che nello schema ho messo una resistenza da 1KOhm, ma è molto alta e potrebbe non consentire il raggiungimento della saturazione e causare un surriscaldamento del transistor: una resistenza da 220 ohm è meglio ;).

    In caso di più LED oppure di carichi un po' superiori (es. le lampadine DC a incandescenza 5V - 250mA che troviamo nelle gettoniere dei nostri cab) possiamo ripiegare su un integrato tipo ULN2003. Questo altro non è che un array di transistor nello stesso package:

    uln2003a



    L’integrato ULN2003 ha le seguenti caratteristiche:

    Tensione di controllo: 5V DC
    Tensione di alimentazione: 5-12V DC
    Corrente massima erogabile: 500 mA sul singolo canale (MAX!), 1A totali.


    In caso di utilizzo di un LED bisognerà indurre un calo di tensione che porti i 5V di alimentazione alla tensione di lavoro del LED (solitamente 3 V per un LED bianco, meno in caso di colore), dunque sarà necessaria una resistenza “R” funzione della corrente di lavoro del LED. Assumendo che il LED assorba 300 mA (dunque un LED da 1W circa, neanche piccolissimo), la resistenza sarà di almeno
    R=V/I = (5-3)V/0.3A=6.6 ohm
    Che approssimiamo al valore commerciale superiore più prossimo che è 6.8 ohm.
    Quando acquisti un LED, le caratteristiche sono sempre riportate; da quelle puoi ricavare il valore della resistenza. >>QUI<< un pratico calcolatore online.

    In alternativa si può utilizzare l'ULN2803 che si differenzia soltanto per il fatto di avere una entrata/uscita in più.

    Come per tutte le soluzioni che vedremo, c'è bisogno di un alimentatore esterno capace di fornire la corrente necessaria ad alimentare le lampadine. L'alimentatore di switching del cab qui va benissimo.

    Questo integrato può servire a noi per azionare fino a 7 LED di potenza ridotta (massimo 1,5W, 300mA) o 3 lampadine DC (5V, 250mA). Le lampadine a incandescenza, infatti, hanno un transiente in accensione che porta ad un assorbimento fino a 10 volte la corrente di lavoro. Dunque, utilizzeremo almeno due ingressi e due uscite del driver per ogni lampadina.
    In caso si preveda che più di due lampade/LED possano lavorare contemporaneamente, bisogna assicurarsi di non superare la corrente massima di 1 A totale; dunque si possono accendere fino a 4 LED contemporaneamente con corrente cadauno massima 250 mA, oppure fino a sette con corrente cadauno 150 mA. Tieni presente comunque che le luci dei cab difficilmente si accendono contemporaneamente.
    Se alimentiamo a 5V, nel caso delle lampadine ad incandescenza la connessione fra uscita dell'integrato e lampadina è diretta dato che si alimentano a 5V. Il collegamento è semplicissimo:

    uln2003wiring



    (Nota che in figura ci sono quattro lampadine, ognuna collegatanad un singolo canale dell'ULN2003. Come dicevo sopra NON è corretto: bisogna limitarsi a tre lampadine massimo sfruttando due linee ciascuna).

    Come nel caso di transistor spiegato sopra, in caso di utilizzo di un LED bisognerà indurre un calo di tensione che porti i 5V di alimentazione alla tensione di lavoro del LED (solitamente 3 V per un LED bianco, meno in caso di colore), dunque sarà necessaria una resistenza “R” funzione della corrente di lavoro del LED.

    ESEMPIO 2 – LED AD ALTA POTENZA
    Per pilotare carichi più importanti di quelli di cui sopra, è necessario sfruttare transistori MOSFET. Esistono diversi tipi di questi, ma noi ci limiteremo ad un paio, sostanzialmente equivalenti: IRL540 e IRLZ44.
    La caratteristica peculiare di questi due signori è di poter accettare al gate segnali di tipo logico (logic level) e poter quindi essere saturati con il segnale in uscita dalla maggior parte delle schede a microcontrollore.

    Un possibile circuito adatto al caso nostro è il seguente:

    MOSFET_DRIVER_LED



    Dove:
    R0 serve a limitare la corrente in uscita dal pin di arduino
    R1 è una resistenza di pulldown (facoltativa)
    LED1 serve a "visualizzare" se ci sia un segnale in ingresso (utile per diagnosi)
    R2 serve a limitare la corrente che alimenta LED1
    Q1 è il nostro transistor MOSFET logic-level
    Power LED è il nostro LED cicciotto
    R3 serve a ridurre la tensione ai capi di Power LED ed è funzione della tensione di alimentazione del circuito

    Le caratteristiche sono:
    Tensione di controllo: 0-5V DC
    Tensione di alimentazione: 5-50V DC
    Corrente massima erogabile: 30A


    Nel caso volessi semplificarti la vita ed acquistare qualcosa di già pronto, esistono dei moduli preconfezionati con circuitistica simile a questa:

    mosfet



    Purtroppo però sfruttano il MOSFET IRF520 il quale per portare in saturazione il gate ha bisogno di 10V. Questo non significa che non funzionerà con i 5V, ma sappi che si scalderà.

    Una seconda alternativa pronta all'uso sono moduli con LED da 3W più driver board integrata. Questi sono semplicissimi da usare e installare e funzionano direttamente a 5V DC (sempre naturalmente forniti da alimentatore esterno).

    3WLED



    Questo modulo in particolare ha le seguenti caratteristiche:

    Tensione di controllo: 5V DC
    Tensione di alimentazione: 5V DC
    Corrente massima erogabile: 500 mA


    Il collegamento è molto semplice: al pin “G” va la massa di un alimentatore esterno (cortocircuitata a quella di arduino), al pin “+” vanno i 5V, sempre prelevati dall’alimentatore esterno, al pin “S” va collegato il pin di arduino che piloterà l’accensione e spegnimento del LED.
    Per i più curiosi: il circuito di driver adottato in questo modulo è praticamente quello dell'esempio 1, con un transistor NPN bello robusto (J3Y) e una resistenza di pulldown da 10Kohm alla sua base (come nel circuito di esempio 2). Il LED è da 3W (750 mA, 3.2-3.9V forward voltage) e viene omessa la resistenza in serie da qualche ohm (e un watt o poco più) che si renderebbe necessaria da buona prassi. Forse un po' al limite per un uso continuo, ma il design è Sparkfun e sono affidabili.

    ESEMPIO 3 – MOTORE DI RUMBLE
    Il circuito di driver che sfrutta transistor MOSFET visto precedentemente può funzionare anche per pilotare motori di rumble. In particolare, il circuito diventa una cosa tipo:

    MOSFET_DRIVER_MOTOR



    Dove al posto del LED abbiamo un motore e in parallelo ad esso un diodo di freewheel. Questo serve ad impedire che la corrente indotta in fase di rallentamento del motore (la quale circola in direzione opposta a quella di "lavoro") finisca per distruggere il transistor. Il diodo di freewheel va scelto adeguatamente. Questo può essere un 1N400X (current rating 1A) se il motore è piccolino, tipo quelli di rumble dei joystick; puoi passare ad un 1N540X (current rating 3A) se il motore a regime consuma 1A o poco più. Bisogna passare a sistemi più sofisticati per correnti superiori. Questo perché in fase di avvio il motore assorbe molto più della sua corrente di regime (anche 10 volte tanto!) e potrebbe bruciarlo subito, portando con se anche il driver (SSR o transistor che sia)... bisogna "stare larghi".
    Nel mio cab di guida ho optato per questa soluzione e ne è venuto fuori il circuitino seguente:

    20200503_142454



    Sullo sfondo vedi il diodo di freewheel che nel caso specifico è un 1N5408, cioè capace di "resistere" ad una corrente fino a 3A.

    Funziona PER-FET-TA-MEN-TE!!

    In caso volessi qualcosa di più semplice, puoi ripiegare su relay a stato solido tipo l’ SSR25DD o SSR40DD.

    SSR-40_DD



    Le caratteristiche di questo signore sono:

    Tensione di controllo: 3-32V DC
    Tensione di alimentazione: 5-60V DC
    Corrente massima erogabile: 40 A (SSR40DD) o 25 A (SSR25DD)
    Nota: la versione con sigla finale “DA” controlla una tensione ALTERNATA e non continua in uscita.


    Il relay a stato solido ha lo svantaggio di essere ingombrante (vabbè: dentro il cab spazio cenn'è); ha però il vantaggio di garantire un isolamento galvanico fra ingresso (lato Arduino dunque) e uscita (lato motore) grazie alla presenza, al suo interno, di uno switch ottico.
    Questi SSR hanno il dissipatore sul fondo: meglio non metterli direttamente a contatto con il legno. Esistono in commercio anche alette di raffreddamento dedicate che consiglio di utilizzare.

    Il collegamento è il seguente:

    SSR40DD_wiring



    Nota che nello schemino c'è una resistenza da 220 ohm fra l'uscita di arduino e il SSR: va messa per limitare la corrente erogata dal pin di arduino e garantire lunga vita alla scheda. Il valore della resistenza non può essere troppo elevato o la corrente erogata dal pin del microcontrollore non riuscirà a portare a saturazione il SSR e questo si scalderá inutilmente. Lo stesso vale quando si usano transistor.

    Il cilindretto nero posto alla base del motore DC è il diodo di ritorno (freewheel diode).
    Nota che massa di arduino e massa del relay NON vanno cortocircuitate proprio perché ingresso e uscita sono volutamente isolate fra loro.
    Attenzione: nel caso si volesse alimentare il motore a 12V, l'alimentatore del cabinato potrebbe non essere sufficiente ad erogare la corrente necessaria. Se il motore è molto grosso, neppure la corrente erogabile dalla linea 5V dello switching nel cab potrebbe bastare. Valuta dunque PRIMA di fare i test quale sia un alimentatore adatto.

    ESEMPIO 4 – CARICHI ALTERNATI - LAMPADE DAYTONA USA
    I relay a stato solido possono convenientemente essere utilizzati come switch per carichi alternati. Per esempio, la SEGA usava spesso SSR per muovere motori alternati e accendere lampade cicciotte nei propri cabinati. Meritano menzione le lampade "Race Leader" del cabinato Daytona USA, dato che sono molto diffuse ancora oggi e le driver board originali cominciano a fare i capricci.
    Un relay a stato solido tipo quello mostrato nell'esempio di cui sopra sarebbe eccessivo per questa applicazione se si considera che SEGA utilizzava SSR da 3A nominali. Un relay tipo quello in figura seguente potrebbe essere più indicato, sia in forma di board, sia "nudo e crudo" senza basetta.

    SSR_0



    Come dicevo sopra, esistono sia relay a stato solido per correnti continue, sia per correnti alternate e non vanno confusi. Devi assicurarti di acquistare la versione che fa al caso tuo.

    Edited by barito - 29/9/2023, 07:29
    File Allegato
    CH341SER.ZIP
    (Number of downloads: 29)

     
    .
0 replies since 21/4/2020, 08:49   628 views
  Share  
.