Visualizzazione post con etichetta Arduino. Mostra tutti i post
Visualizzazione post con etichetta Arduino. Mostra tutti i post

martedì 8 ottobre 2019

M5Stack Fire





Per interagire con MicroPython direttamente su M5Stack Fire ci si puo' collegare via USB

Si collega il cavo, si apre un terminale seriale e si preme CTRL+C dopo aver premuto il tasto di reset.




Se si usa Minicom si deve disabilitare il controllo di flusso (altrimenti non viene lanciato CTRL+C)


A questo punto si possono inserire comandi Python mediante REPL

Per interagire con il filesystem si puo' usare ampy

ampy --port /dev/ttyUSB0 rm file.py  (cancella file)
ampy --port /dev/ttyUSB0 mkdir test  (crea dir)
ampy --port /dev/ttyUSB0 ls  (lista)
ampy --port /dev/ttyUSB0 put test.py  test/test.py  (carica un file dal computer al Fire)

Un altro metodo comodo per programmare e' usare VSCode (anche in Linux) usando il plugin m5stack-mpy (si installa usando le istruzioni a questo link)


Una volta installato il plugin si clicca Add M5Stack nella barra in basso e si seleziona la checkbox della porta seriale. Si apre quindi il menu a tendina M5Stack Device da cui si possono gestire anche la cancellazione e creazione dei file nel filesystem

Il metodo forse piu' potente per programmare M5Stack Fire e' usare la Arduino IDE
Si deve aggiungere tra le board il link

https://dl.espressif.com/dl/package_esp32_index.json

Si aggiunge poi la libreria M5Stack direttamente la library manager di Arduino IDE

venerdì 24 maggio 2019

Lunghezza cavi I2C

Volevo vedere se riuscivo a fare a meno di un microcontrollore e seriale provando a spedire dati da un accelerometro I2C direttamente ad una altro microcontrollore distanza una decina di metri



Leggendo su Internet si vede che I2C e' nato per mettere in comunicazione dispositivi sullo stesso integrato ma qualcuno a provato ad abbassare la velocita' di trasferimento (I2C lavora di norma a 100 KHz o 400 KHz) e dei cavi twisted derivati da un comune cavo UTP

Dopo un po' di prove ho rinunciato visto che anche con il semplice sketch I2C scanner non ricevevo rispsosta...ho visto che esistono dei dispositivi I2C extender basati su PCF8574 ma a questo punto tale vale ritornano alla piu' collaudata ed affidabile RS485

In generale non ho misurato perdita di tensione sul cavo ma il problema dovrebbe essere la capacitanza (che non ho gli strumenti per misurarla)

giovedì 2 maggio 2019

4x4 Keypad su Arduino

Per connettere un keypad 4x4 ad una Arduino sono necessari 8 cavi di collegamento. In questo caso il pin piu' a sinistra del connettore della tasteria (colore blu) si collega al pin D9 di Arduino e cosi' via scendendo via al pin D2




http://osoyoo.com/2017/09/arduino-lesson-4x4-matrix-keypad/

---------------------------------------------------------------
#include <Keypad.h>

const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = {
 {'1', '2', '3', 'A'},
 {'4', '5', '6', 'B'},
 {'7', '8', '9', 'C'},
 {'*', '0', '#', 'D'}
};

byte rowPins[ROWS] = {9,8,7,6};//righe
byte colPins[COLS] = {5,4,3,2}; //colonne

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );


void setup(){
  Serial.begin(9600);
}
  
void loop(){
  char key = keypad.getKey();
  
  if (key){
    Serial.println(key);
  }
}

Emulatore CHIP-8 su Arduino Mega

Partendo dal precedente post ho portato il codice su Arduino

Per il progetto ho usato una Arduino Mega con un schermo Oled 0.91" di 128x32 pixels (il CHIP-8 aveva uno schermo 64x32 monocromatico basato su U8G2) ed un keypad a 16 pulsanti (CHIP-8 gestiva una tastiera a 16 tasti)






il primo passo e' stato quello di usare la classe chip8 per creare una libreria Arduino.
Si crea un sottodirectory chip8 in /libraries e si creano i file chip8.cpp e chip8.h

Rispetto alla versione NCurses sono stati rimossi dei comandi che hanno riscontro in Arduino (per esempio iostream o sizeof ) Credits James Griffin

chip8.cpp
-----------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
//#include <iostream>
//#include <random>
#include "time.h"


#include "chip8.h"

unsigned char chip8_fontset[80] =
{
    0xF0, 0x90, 0x90, 0x90, 0xF0, //0
    0x20, 0x60, 0x20, 0x20, 0x70, //1
    0xF0, 0x10, 0xF0, 0x80, 0xF0, //2
    0xF0, 0x10, 0xF0, 0x10, 0xF0, //3
    0x90, 0x90, 0xF0, 0x10, 0x10, //4
    0xF0, 0x80, 0xF0, 0x10, 0xF0, //5
    0xF0, 0x80, 0xF0, 0x90, 0xF0, //6
    0xF0, 0x10, 0x20, 0x40, 0x40, //7
    0xF0, 0x90, 0xF0, 0x90, 0xF0, //8
    0xF0, 0x90, 0xF0, 0x10, 0xF0, //9
    0xF0, 0x90, 0xF0, 0x90, 0x90, //A
    0xE0, 0x90, 0xE0, 0x90, 0xE0, //B
    0xF0, 0x80, 0x80, 0x80, 0xF0, //C
    0xE0, 0x90, 0x90, 0x90, 0xE0, //D
    0xF0, 0x80, 0xF0, 0x80, 0xF0, //E
    0xF0, 0x80, 0xF0, 0x80, 0x80  //F
};



Chip8::Chip8() {}
Chip8::~Chip8() {}

// Initialise
void Chip8::init() {
    pc      = 0x200;    // Set program counter to 0x200
    opcode  = 0;        // Reset op code
    I     = 0;          // Reset I
    sp      = 0;        // Reset stack pointer

    // Clear the display
    for (int i = 0; i < 2048; ++i) {
        gfx[i] = 0;
    }

    // Clear the stack, keypad, and V registers
    for (int i = 0; i < 16; ++i) {
        stack[i]    = 0;
        key[i]      = 0;
        V[i]        = 0;
    }

    // Clear memory
    for (int i = 0; i < 4096; ++i) {
        memory[i] = 0;
    }

    // Load font set into memory
    for (int i = 0; i < 80; ++i) {
        memory[i] = chip8_fontset[i];
    }

    // Reset timers
    delay_timer = 0;
    sound_timer = 0;

    // Seed rng
    srand (time(NULL));
}

// Initialise and load ROM into memory
bool Chip8::load(unsigned char programma[],int size) {
    // Initialise
    init();

    //long rom_size = sizeof(programma);
    int rom_size = size;
    // Copy buffer to memory
    if ((4096-512) > rom_size){
        for (int i = 0; i < rom_size; ++i) {
            memory[i + 512] = (uint8_t)programma[i];   // Load into memory starting
                                                        // at 0x200 (=512)
        }
    }
    else {
        //std::cerr << "ROM too large to fit in memory" << std::endl;
        return false;
    }

    return true;
}

// Emulate one cycle
void Chip8::emulate_cycle() {

    // Fetch op code
    opcode = memory[pc] << 8 | memory[pc + 1];   // Op code is two bytes

    switch(opcode & 0xF000){

        // 00E_
        case 0x0000:

            switch (opcode & 0x000F) {
                // 00E0 - Clear screen
                case 0x0000:
                    for (int i = 0; i < 2048; ++i) {
                        gfx[i] = 0;
                    }
                    drawFlag = true;
                    pc+=2;
                    break;

                // 00EE - Return from subroutine
                case 0x000E:
                    --sp;
                    pc = stack[sp];
                    pc += 2;
                    break;

                default:
                    //printf("\nUnknown op code: %.4X\n", opcode);
                    exit(3);
            }
            break;

        // 1NNN - Jumps to address NNN
        case 0x1000:
            pc = opcode & 0x0FFF;
            break;

        // 2NNN - Calls subroutine at NNN
        case 0x2000:
            stack[sp] = pc;
            ++sp;
            pc = opcode & 0x0FFF;
            break;

        // 3XNN - Skips the next instruction if VX equals NN.
        case 0x3000:
            if (V[(opcode & 0x0F00) >> 8] == (opcode & 0x00FF))
                pc += 4;
            else
                pc += 2;
            break;

        // 4XNN - Skips the next instruction if VX does not equal NN.
        case 0x4000:
            if (V[(opcode & 0x0F00) >> 8] != (opcode & 0x00FF))
                pc += 4;
            else
                pc += 2;
            break;

        // 5XY0 - Skips the next instruction if VX equals VY.
        case 0x5000:
            if (V[(opcode & 0x0F00) >> 8] == V[(opcode & 0x00F0) >> 4])
                pc += 4;
            else
                pc += 2;
            break;

        // 6XNN - Sets VX to NN.
        case 0x6000:
            V[(opcode & 0x0F00) >> 8] = opcode & 0x00FF;
            pc += 2;
            break;

        // 7XNN - Adds NN to VX.
        case 0x7000:
            V[(opcode & 0x0F00) >> 8] += opcode & 0x00FF;
            pc += 2;
            break;

        // 8XY_
        case 0x8000:
            switch (opcode & 0x000F) {

                // 8XY0 - Sets VX to the value of VY.
                case 0x0000:
                    V[(opcode & 0x0F00) >> 8] = V[(opcode & 0x00F0) >> 4];
                    pc += 2;
                    break;

                // 8XY1 - Sets VX to (VX OR VY).
                case 0x0001:
                    V[(opcode & 0x0F00) >> 8] |= V[(opcode & 0x00F0) >> 4];
                    pc += 2;
                    break;

                // 8XY2 - Sets VX to (VX AND VY).
                case 0x0002:
                    V[(opcode & 0x0F00) >> 8] &= V[(opcode & 0x00F0) >> 4];
                    pc += 2;
                    break;

                // 8XY3 - Sets VX to (VX XOR VY).
                case 0x0003:
                    V[(opcode & 0x0F00) >> 8] ^= V[(opcode & 0x00F0) >> 4];
                    pc += 2;
                    break;

                // 8XY4 - Adds VY to VX. VF is set to 1 when there's a carry,
                // and to 0 when there isn't.
                case 0x0004:
                    V[(opcode & 0x0F00) >> 8] += V[(opcode & 0x00F0) >> 4];
                    if(V[(opcode & 0x00F0) >> 4] > (0xFF - V[(opcode & 0x0F00) >> 8]))
                        V[0xF] = 1; //carry
                    else
                        V[0xF] = 0;
                    pc += 2;
                    break;

                // 8XY5 - VY is subtracted from VX. VF is set to 0 when
                // there's a borrow, and 1 when there isn't.
                case 0x0005:
                    if(V[(opcode & 0x00F0) >> 4] > V[(opcode & 0x0F00) >> 8])
                        V[0xF] = 0; // there is a borrow
                    else
                        V[0xF] = 1;
                    V[(opcode & 0x0F00) >> 8] -= V[(opcode & 0x00F0) >> 4];
                    pc += 2;
                    break;

                // 0x8XY6 - Shifts VX right by one. VF is set to the value of
                // the least significant bit of VX before the shift.
                case 0x0006:
                    V[0xF] = V[(opcode & 0x0F00) >> 8] & 0x1;
                    V[(opcode & 0x0F00) >> 8] >>= 1;
                    pc += 2;
                    break;

                // 0x8XY7: Sets VX to VY minus VX. VF is set to 0 when there's
                // a borrow, and 1 when there isn't.
                case 0x0007:
                    if(V[(opcode & 0x0F00) >> 8] > V[(opcode & 0x00F0) >> 4]) // VY-VX
                        V[0xF] = 0; // there is a borrow
                    else
                        V[0xF] = 1;
                    V[(opcode & 0x0F00) >> 8] = V[(opcode & 0x00F0) >> 4] - V[(opcode & 0x0F00) >> 8];
                    pc += 2;
                    break;

                // 0x8XYE: Shifts VX left by one. VF is set to the value of
                // the most significant bit of VX before the shift.
                case 0x000E:
                    V[0xF] = V[(opcode & 0x0F00) >> 8] >> 7;
                    V[(opcode & 0x0F00) >> 8] <<= 1;
                    pc += 2;
                    break;

                default:
                    //printf("\nUnknown op code: %.4X\n", opcode);
                    exit(3);
            }
            break;

        // 9XY0 - Skips the next instruction if VX doesn't equal VY.
        case 0x9000:
            if (V[(opcode & 0x0F00) >> 8] != V[(opcode & 0x00F0) >> 4])
                pc += 4;
            else
                pc += 2;
            break;

        // ANNN - Sets I to the address NNN.
        case 0xA000:
            I = opcode & 0x0FFF;
            pc += 2;
            break;

        // BNNN - Jumps to the address NNN plus V0.
        case 0xB000:
            pc = (opcode & 0x0FFF) + V[0];
            break;

        // CXNN - Sets VX to a random number, masked by NN.
        case 0xC000:
            V[(opcode & 0x0F00) >> 8] = (rand() % (0xFF + 1)) & (opcode & 0x00FF);
            pc += 2;
            break;

        // DXYN: Draws a sprite at coordinate (VX, VY) that has a width of 8
        // pixels and a height of N pixels.
        // Each row of 8 pixels is read as bit-coded starting from memory
        // location I;
        // I value doesn't change after the execution of this instruction.
        // VF is set to 1 if any screen pixels are flipped from set to unset
        // when the sprite is drawn, and to 0 if that doesn't happen.
        case 0xD000:
        {
            unsigned short x = V[(opcode & 0x0F00) >> 8];
            unsigned short y = V[(opcode & 0x00F0) >> 4];
            unsigned short height = opcode & 0x000F;
            unsigned short pixel;

            V[0xF] = 0;
            for (int yline = 0; yline < height; yline++)
            {
                pixel = memory[I + yline];
                for(int xline = 0; xline < 8; xline++)
                {
                    if((pixel & (0x80 >> xline)) != 0)
                    {
                        if(gfx[(x + xline + ((y + yline) * 64))] == 1)
                        {
                            V[0xF] = 1;
                        }
                        gfx[x + xline + ((y + yline) * 64)] ^= 1;
                    }
                }
            }

            drawFlag = true;
            pc += 2;
        }
            break;

        // EX__
        case 0xE000:

            switch (opcode & 0x00FF) {
                // EX9E - Skips the next instruction if the key stored
                // in VX is pressed.
                case 0x009E:
                    if (key[V[(opcode & 0x0F00) >> 8]] != 0)
                        pc +=  4;
                    else
                        pc += 2;
                    break;

                // EXA1 - Skips the next instruction if the key stored
                // in VX isn't pressed.
                case 0x00A1:
                    if (key[V[(opcode & 0x0F00) >> 8]] == 0)
                        pc +=  4;
                    else
                        pc += 2;
                    break;

                default:
                    //printf("\nUnknown op code: %.4X\n", opcode);
                    exit(3);
            }
            break;

        // FX__
        case 0xF000:
            switch(opcode & 0x00FF)
            {
                // FX07 - Sets VX to the value of the delay timer
                case 0x0007:
                    V[(opcode & 0x0F00) >> 8] = delay_timer;
                    pc += 2;
                    break;

                // FX0A - A key press is awaited, and then stored in VX
                case 0x000A:
                {
                    bool key_pressed = false;

                    for(int i = 0; i < 16; ++i)
                    {
                        if(key[i] != 0)
                        {
                            V[(opcode & 0x0F00) >> 8] = i;
                            key_pressed = true;
                        }
                    }

                    // If no key is pressed, return and try again.
                    if(!key_pressed)
                        return;

                    pc += 2;
                }
                    break;

                // FX15 - Sets the delay timer to VX
                case 0x0015:
                    delay_timer = V[(opcode & 0x0F00) >> 8];
                    pc += 2;
                    break;

                // FX18 - Sets the sound timer to VX
                case 0x0018:
                    sound_timer = V[(opcode & 0x0F00) >> 8];
                    pc += 2;
                    break;

                // FX1E - Adds VX to I
                case 0x001E:
                    // VF is set to 1 when range overflow (I+VX>0xFFF), and 0
                    // when there isn't.
                    if(I + V[(opcode & 0x0F00) >> 8] > 0xFFF)
                        V[0xF] = 1;
                    else
                        V[0xF] = 0;
                    I += V[(opcode & 0x0F00) >> 8];
                    pc += 2;
                    break;

                // FX29 - Sets I to the location of the sprite for the
                // character in VX. Characters 0-F (in hexadecimal) are
                // represented by a 4x5 font
                case 0x0029:
                    I = V[(opcode & 0x0F00) >> 8] * 0x5;
                    pc += 2;
                    break;

                // FX33 - Stores the Binary-coded decimal representation of VX
                // at the addresses I, I plus 1, and I plus 2
                case 0x0033:
                    memory[I]     = V[(opcode & 0x0F00) >> 8] / 100;
                    memory[I + 1] = (V[(opcode & 0x0F00) >> 8] / 10) % 10;
                    memory[I + 2] = V[(opcode & 0x0F00) >> 8] % 10;
                    pc += 2;
                    break;

                // FX55 - Stores V0 to VX in memory starting at address I
                case 0x0055:
                    for (int i = 0; i <= ((opcode & 0x0F00) >> 8); ++i)
                        memory[I + i] = V[i];

                    // On the original interpreter, when the
                    // operation is done, I = I + X + 1.
                    I += ((opcode & 0x0F00) >> 8) + 1;
                    pc += 2;
                    break;

                case 0x0065:
                    for (int i = 0; i <= ((opcode & 0x0F00) >> 8); ++i)
                        V[i] = memory[I + i];

                    // On the original interpreter,
                    // when the operation is done, I = I + X + 1.
                    I += ((opcode & 0x0F00) >> 8) + 1;
                    pc += 2;
                    break;

                default:
break;
                    //printf ("Unknown opcode [0xF000]: 0x%X\n", opcode);
            }
            break;

        default:
            //printf("\nUnimplemented op code: %.4X\n", opcode);
            exit(3);
    }


    // Update timers
    if (delay_timer > 0)
        --delay_timer;

    if (sound_timer > 0)
        if(sound_timer == 1);
            // TODO: Implement sound
        --sound_timer;

}
-----------------------------------------------------------------


chip8.h
-----------------------------------------------------------------
#ifndef CHIP_8_H
#define CHIP_8_H

#include <stdint.h>

class Chip8 {
private:
    uint16_t stack[16];                 // Stack
    uint16_t sp;                        // Stack pointer

    uint8_t memory[4096];               // Memory (4k)
    uint8_t V[16];                      // V registers (V0-VF)

    uint16_t pc;                        // Program counter
    uint16_t opcode;                    // Current op code
    uint16_t I;                         // Index register

    uint8_t delay_timer;                // Delay timer
    uint8_t sound_timer;                // Sound timer

    void init();

public:
    uint8_t  gfx[64 * 32];              // Graphics buffer
    uint8_t  key[16];                   // Keypad
    bool drawFlag;                      // Indicates a draw has occurred

    Chip8();
    ~Chip8();

    void emulate_cycle();               // Emulate one cycle
    bool load(unsigned char programma[],int size);   // Load application
};

#endif // CHIP_8_H
-----------------------------------------------------------------

chip8_pong.ino
-----------------------------------------------------------------
#include <Arduino.h>
#include <U8g2lib.h>
#include <SPI.h>
#include <Wire.h>

#include <Keypad.h>


#include <chip8.h>

U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0); 


Chip8 chip8 = Chip8();

unsigned char prg[] =
{
    0x6A,0x02, 0x6B, 0x0C, 0x6C, 0x3F, 0x6D, 0x0C,
    0xA2,0xEA, 0xDA, 0xB6, 0xDC, 0xD6, 0x6E, 0x00,
    0x22,0xD4, 0x66, 0x03, 0x68, 0x02, 0x60, 0x60,
    0xF0,0x15, 0xF0, 0x07, 0x30, 0x00, 0x12, 0x1A,
    0xC7,0x17, 0x77, 0x08,

    0x69,0xFF, 0xA2, 0xF0, 0xD6, 0x71, 0xA2, 0xEA,
    0xDA,0xB6, 0xDC, 0xD6, 0x60, 0x01, 0xE0, 0xA1,
    0x7B,0xFE, 0x60, 0x04, 0xE0, 0xA1, 0x7B, 0x02,
    0x60,0x1F, 0x8B, 0x02, 0xDA, 0xB6, 0x60, 0x0C,
    0xE0,0xA1, 0x7D, 0xFE,

    0x60,0x0D, 0xE0, 0xA1, 0x7D, 0x02, 0x60, 0x1F,
    0x8D,0x02, 0xDC, 0xD6, 0xA2, 0xF0, 0xD6, 0x71,
    0x86,0x84, 0x87, 0x94, 0x60, 0x3F, 0x86, 0x02,
    0x61,0x1F, 0x87, 0x12, 0x46, 0x02, 0x12, 0x78,
    0x46,0x3F, 0x12, 0x82,

    0x47,0x1F, 0x69, 0xFF, 0x47, 0x00, 0x69, 0x01,
    0xD6,0x71, 0x12, 0x2A, 0x68, 0x02, 0x63, 0x01,
    0x80,0x70, 0x80, 0xB5, 0x12, 0x8A, 0x68, 0xFE,
    0x63,0x0A, 0x80, 0x70, 0x80, 0xD5, 0x3F, 0x01,
    0x12,0xA2, 0x61, 0x02,

    0x80,0x15, 0x3F, 0x01, 0x12, 0xBA, 0x80, 0x15,
    0x3F,0x01, 0x12, 0xC8, 0x80, 0x15, 0x3F, 0x01,
    0x12,0xC2, 0x60, 0x20, 0xF0, 0x18, 0x22, 0xD4,
    0x8E,0x34, 0x22, 0xD4, 0x66, 0x3E, 0x33, 0x01,
    0x66,0x03, 0x68, 0xFE,

    0x33,0x01, 0x68, 0x02, 0x12, 0x16, 0x79, 0xFF,
    0x49,0xFE, 0x69, 0xFF, 0x12, 0xC8, 0x79, 0x01,
    0x49,0x02, 0x69, 0x01, 0x60, 0x04, 0xF0, 0x18,
    0x76,0x01, 0x46, 0x40, 0x76, 0xFE, 0x12, 0x6C,
    0xA2,0xF2, 0xFE, 0x33,

    0xF2,0x65, 0xF1, 0x29, 0x64, 0x14, 0x65, 0x00,
    0xD4,0x55, 0x74, 0x15, 0xF2, 0x29, 0xD4, 0x55,
    0x00,0xEE, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    0x80,0x00, 0x00, 0x00, 0x00, 0x00

};


const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = {
 {'1', '2', '3', 'A'},
 {'4', '5', '6', 'B'},
 {'7', '8', '9', 'C'},
 {'*', '0', '#', 'D'}
};

byte rowPins[ROWS] = {9,8,7,6}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {5,4,3,2}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup() {
    Serial.begin(9600);
    u8g2.begin();
    chip8.load(prg,246); // non c'e' la funzione sizeof

}

void loop() {
  chip8.emulate_cycle();
  char key = keypad.getKey();
  if (key){
    for (int f=0; f<16; f++)
          {
            chip8.key[f] = 0; 
          }

    Serial.println(key);
    switch(key)
        {
          case '1':
            chip8.key[1]=1;
            break;
          case '4':
            chip8.key[4]=1;
            break;
          case '7':
            chip8.key[7]=1;
            break;
          case '*':
            chip8.key[10]=1;
            break;
      /////////////////////////////////////
          case '2':
            chip8.key[2]=1;
            break;
          case '5':
            chip8.key[5]=1;
            break;
          case '8':
            chip8.key[8]=1;
            break;
          case '0':
            chip8.key[0]=1;
            break;
      /////////////////////////////////////
          case '3':
            chip8.key[3]=1;
            break;
          case '6':
            chip8.key[6]=1;
            break;
          case '9':
            chip8.key[9]=1;
            break;
          case '#':
            chip8.key[11]=1;
            break;
      
      /////////////////////////////////////
          case 'A':
            chip8.key[12]=1;
            break;
          case 'B':
            chip8.key[13]=1;
            break;
          case 'C':
            chip8.key[14]=1;
            break;
          case 'D':
            chip8.key[15]=1;
            break;
          default:
            break;
            
        }
  }
  
  if (chip8.drawFlag) {
            chip8.drawFlag = false;
            u8g2.clearBuffer();
            for (int i = 0; i < 2048; ++i) {
                uint8_t pixel = chip8.gfx[i];
                int k = (int)i/64;
                int j = i%64;
                if (pixel == 1)
                {
                  //u8g2.clearBuffer();
                  u8g2.drawPixel(j,k);
                  
                  //move(k,j);
                  //addch(ACS_CKBOARD);
                }
            }
            //refresh();
            //u8g2.clearBuffer();
            u8g2.sendBuffer();
        }
   delay(2);
}

sabato 20 aprile 2019

Ardino port busy su Debian

Cercando di fare l'upload di uno sketch sulla nuova arrivata, un clone cinese di una Arduino Esplora, mi sono trovato nei guai perche' ogni volta c'erano errori di scrittura, errori nella fase di verifica o addirittura tutto era bloccato da un messaggio di Port Busy



la soluzione a tutti i problemi non era nell'Arduino, ne' nel cavo ne' nella IDE...in pratica il pacchetto modem manager entra in conflitto con l'upload. Basta eseguire

apt-get purge modemmanager

e tutto funziona

venerdì 12 aprile 2019

FTDI232 e Arduino Mini Pro

Dovendo fare un progetto microscopico ho dovuto tirare fuori una Arduino Mini Pro che non avevo mai usato. Per programmarla ho scoperto che non e' necessario saldare i pin sulla scheda


E' sufficiente appoggiare i pin del programmatore FTDI232 sulla Mini Pro e si ottiene una connessione sufficientemente stabile per programmare la scheda

lunedì 8 aprile 2019

Arduino Nano Eleggo Old Bootloader

Stavo impazzendo con un clone di una Arduino Nano Elegoo perche' non riuscivo a caricare nessuno sketch


..quando e' saltato un messaggio su un forum che le Arduino Nano possono avere due bootloader e che si puo' selezionare dalla Arduino Ide. Nel mio caso era da selezionare Old Bootloader


mercoledì 3 aprile 2019

Update MKRWAN1300 firmware

AGGIORNAMENTO : come suggerito dal forum di Arduino c'e' un metodo molto piu' semplice. Si aggiorna la libreria MKRWAN e poi si lancia lo skecth MKRWANFWUpdate_standalone. Nella directory della libreria c'e' l'ultimo firmware disponibile senza la necesssita' di scaricarlo a parte



Per aggiornare il firmware di una Arduino MKR1300 si parte scaricando il firmware compilato da link https://github.com/arduino/mkrwan1300-fw/releases


Al momento di scrivere questa nota l'ultima release e' la 1.1.6 (la 1.1.9 non risulta in formato bin) mentre nella Mkr1300 che mi e' arrivata e' montato un ARD-078 1.1.5

Si copia il file mlm32l07x01.bin nella stessa directory dove e' presente lo sketch MKRWANFWUpdate_standalone incluso negli esempi della libreria MKRWAN e si lancia il comando da terminale

echo -n "const " > fw.h && xxd -i mlm32l07x01.bin >> fw.h

si lancia quindi  lo sketch ed aprendo il terminale seriale si vedranno i seguenti comandi


Wrote and verified address 0x08012700 (98%)
 Wrote and verified address 0x08012800 (98%)
 Wrote and verified address 0x08012900 (98%)
 Wrote and verified address 0x08012a00 (99%)
 Wrote and verified address 0x08012b00 (99%)
 Wrote and verified address 0x08012c00 (99%)
 Wrote and verified address 0x08012d00 (100%)
 Done.

Starting execution at address 0x08000000... done.
Flashing ok :)
ARD-078 1.1.6

venerdì 29 marzo 2019

Dragino LG01 Lora Gateway su TheThingsNetwork

Un gateway Lora e' un dispositivo che legge il traffico Lora e lo rilancia su Internet e nel caso sul cloud di TheThingsNetwork (abbreviato TTN)
Ci sono molti Gateway Lora compreso quello originale Arduino ma a causa dei costi (Lora Gateway Arduino costa circa 350 euro) ho preso Dragino LG01, a canale singolo 868 MHz (standard Italia) che e' molto simile ad una Arduino Yun (si  programma via Arduino IDE con la libreria Bridge)


Le istruzioni ufficiale si trovano al link seguente
https://wiki.dragino.com/index.php?title=Connect_to_TTN#Create_TTN_account

(il manuale completo si trova qui)

Ma prima di iniziare si deve creare un account se TheThingsNetwork, andare nella console a creare un Gateway


Per il codice identificativo si puo'utilizzare il Mac Address (riempiendo i byte rimanenti per arrivare a 16 con FF) ed impostando Legacy Packet Forwarder

Successivamente ci si collega alla WiFi aperta del Dragino al 10.130.1.1 (od alla porta LAN) con le credenziali root/dragino. Il sistema di base e' OpenWRT per cui e' semplice configurare l'access point in WPA e controllare che il gateway sia connesso ad Internet


Si va poi sul Dragino e si scarica da qui  il file single_pkt_fwd_v004.hex. Attenzione : il file sul server si chiama single_pkt_fwd_v004.ino.hex... ho dovuto rinominare il file
Poi si va Sensor/Flash MCU, si seleziona il file sopra indicato e si aggiorna. Da questa pagina si puo' controllare che il caricamento sia avvenuto in modo corretto



Si imposta la radio sullo standard europeo


Si configura il Lora Gateway per dialogare con TheThingsNetwork indicando l'indirizzo router.eu.thethings.network, ed il Gateway ID che e' riportato nella consolle di TTN (ma senza i primi 4 caratteri ovvero senza eui-)




e si seleziona LorWan come IoT server


Se tutto e' andato bene sulla consolle di TTN il gateway sara' visto come online 

Opencv camera calibration in cpp

Oltre che con uno script Python come visto qui la calibrazione della camera si puo' fare anche con il programma in CPP Questo il proce...