Manual

do

Maker

.

com

(Des)Corretor ortográfico com Arduino

(Des)Corretor ortográfico com Arduino

Muitas pessoas usam o Arduino para trabalho, outros tantos para aprendizado, mais um monte para diversão. Eu gosto de usar pra diversão. O Arduino, vendo-o como um brinquedo, atende a todas as idades. Nesse artigo vou mostrar como é simples fazer um (des)corretor ortográfico com Arduino. O mais legal é que não implementei todas as possibilidades, apenas alguns exemplos.

Materiais necessários

Para esse artigo é fundamental que o Arduino seja o Leonardo (que você encontra nesse link da Eletrogate) e também é necessário o USB Shield (também na Eletrogate, por esse link), que fará a bridge entre o teclado e o computador.

Como funciona o (des)corretor ortográfico com Arduino

O USB Host Shield serve para diversas coisas, como controles de PS4, XBOX, interface com smartphones etc. Nesse artigo utilizo a funcionalidade de dispositivo de entrada - no caso, o teclado. Quando algo é digitado no teclado, é feita a leitura, então o valor é convertido para o equivalente ao char da tabela ASCII. Nesse momento já podemos interagir com os valores.

Para enviar ao computador, o Arduino Leonardo tem a habilidade de funcionar como um teclado, então usamos esse recurso para repassar o que manipulamos da recepção do teclado. Resumindo:

  • Teclado para o shield
  • Shield para o Arduino
  • Manipulação dos caracteres
  • repasse para o computador

Nem me preocupei em escrever "from scratch", modifiquei o sketch do USB Host Shield e adicionei a funcionalidade de teclado ao Arduino Leonardo, bem simples. Criei algumas funções para manipular os caracteres de entrada antes de repassar ao computador, então, se uma pessoa começar a digitar e não souber dessa "sacanagem", vai ficar doida tentando corrigir o texto!

Sugestões de implementação

Coloquei apenas a mudança de G para J, de M para N, de N para M e C para C. Outras implementações que seriam interessantes:

  • X para S, quando procedido de consoante
  • X para CH, quando procedido de vogal
  • SS para Ç
  • Z para S, quando a posição de leitura for > 0
  • etc

A biblioteca para o Arduino Leonardo se comportar como um teclado é nativa. Já a do USB Host Shield.

O código que utilizei pro exemplo mais abaixo ficou assim:

#include <hidboot.h>
#include <usbhub.h>
#include "Keyboard.h"

// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>

unsigned char words[20] = {0};
byte i = 0;
class KbdRptParser : public KeyboardReportParser
{
    void PrintKey(uint8_t mod, uint8_t key);
    protected: void OnControlKeysChanged(uint8_t before, uint8_t after);
        void OnKeyDown (uint8_t mod, uint8_t key);
        void OnKeyUp (uint8_t mod, uint8_t key);
        void OnKeyPressed(uint8_t key);
    };

void change_mn(unsigned char checkS)
{
    if (i == 0) return; if (checkS == 'm')
    {
        i = i-1; words[i] = 'n';
    }
}

void change_nm(unsigned char checkS)
{
    if (i == 0) return;
    if (checkS == 'n')
    {
        i = i-1;
        words[i] = 'm';
    }
}

void change_gj(unsigned char checkS)
{
    if (checkS == 'g')
    {
        i = i > 0 ? i-1 : 0; words[i] = 'j';
    }
}

void change_cs(unsigned char checkS)
{
    if (checkS == 'c' && i == 0)
    {
        words[i] = 's';
    }
}

void clearWord(unsigned char key_pressed)
{
    if (key_pressed == ' ' || i >18)
    {
        Serial.println("");
        Serial.print("word: ");
        //Serial.println(words);
        for (byte a = 0; a < 20;a++)
        {
            words[a] = 0;
        }
        i = 0;
    } else {
            i += 1;
            //Serial.println(words);
    }
}

void KbdRptParser::PrintKey(uint8_t m, uint8_t key)
{
    MODIFIERKEYS mod;
    *((uint8_t*)&mod) = m;
    Serial.print((mod.bmLeftCtrl == 1) ? "C" : " ");
    Serial.print((mod.bmLeftShift == 1) ? "S" : " ");
    Serial.print((mod.bmLeftAlt == 1) ? "A" : " ");
    Serial.print((mod.bmLeftGUI == 1) ? "G" : " ");

    Serial.print(" >");
    PrintHex<uint8_t>(key, 0x80);
    Serial.print("< ");

    Serial.print((mod.bmRightCtrl == 1) ? "C" : " ");
    Serial.print((mod.bmRightShift == 1) ? "S" : " ");
    Serial.print((mod.bmRightAlt == 1) ? "A" : " ");
    Serial.print((mod.bmRightGUI == 1) ? "G" : " ");
};

void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key)
{
    //Serial.print("DN ");
    //PrintKey(mod, key);
    uint8_t c = OemToAscii(mod, key);

    if (c)
        OnKeyPressed(c);
}

void KbdRptParser::OnControlKeysChanged(uint8_t before, uint8_t after)
{
    MODIFIERKEYS beforeMod;
    *((uint8_t*)&beforeMod) = before;
    MODIFIERKEYS afterMod;
    *((uint8_t*)&afterMod) = after;
    if (beforeMod.bmLeftCtrl != afterMod.bmLeftCtrl)
    {
        Serial.print("LeftCtrl changed");
    }

    if (beforeMod.bmLeftShift != afterMod.bmLeftShift)
    {
        Serial.print("LeftShift changed");
    }

    if (beforeMod.bmLeftAlt != afterMod.bmLeftAlt)
    {
        Serial.print("LeftAlt changed");
    }

    if (beforeMod.bmLeftGUI != afterMod.bmLeftGUI)
    {
        Serial.print("LeftGUI changed");
    }

    if (beforeMod.bmRightCtrl != afterMod.bmRightCtrl)
    {
        Serial.print("RightCtrl changed");
    }

    if (beforeMod.bmRightShift != afterMod.bmRightShift)
    {
        Serial.print("RightShift changed");
    }

    if (beforeMod.bmRightAlt != afterMod.bmRightAlt)
    {
        Serial.print("RightAlt changed");
    }
    
    if (beforeMod.bmRightGUI != afterMod.bmRightGUI)
    {
        Serial.print("RightGUI changed");
    }
}

void KbdRptParser::OnKeyUp(uint8_t mod, uint8_t key)
{
    //Serial.print("UP ");
    //PrintKey(mod, key);
}

void KbdRptParser::OnKeyPressed(uint8_t key)
{
    char pressed = (unsigned char) key;
    words[i] = pressed;
    change_mn(pressed);
    change_nm(pressed);
    change_cs(pressed);
    change_gj(pressed);

    Keyboard.write(words[i]);

    clearWord(pressed);
    Serial.print(pressed);
    Serial.print(i);
};

USB Usb;
//USBHub Hub(&Usb);
HIDBoot<USB_HID_PROTOCOL_KEYBOARD> HidKeyboard(&Usb);

KbdRptParser Prs;

void setup()
{
    Serial.begin(115200);
    Keyboard.begin();
    #if !defined(__MIPSEL__)
        while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
    #endif

    Serial.println("Starting...");
    if (Usb.Init() == -1)
        Serial.print("OSC did not start.");

    delay(200);
    HidKeyboard.SetReportParser(0, &Prs);
}

void loop()
{
    Usb.Task();
}

O vídeo mostrando uma frase. Acabei escrevendo 'sin' e daí saiu certo o 'sim'.

Inscreva-se no nosso canal Manual do Maker no YouTube.

Próximo post a caminho!

Revisão: Ricardo Amaral de Andrade

Nome do Autor

Djames Suhanko

Autor do blog "Do bit Ao Byte / Manual do Maker".

Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.