Arquivo da Categoria: Sem categoria

RPi setup

Serviço para arrancar meteo.py:

sudo nano -w /etc/systemd/system/meteo.service

[Unit]
Description=meteo
After=network.target

[Service]
Type=simple
User=%i
ExecStart=/usr/bin/python /home/pi/python/meteo/meteo.py

[Install]
WantedBy=multi-user.target

sudo systemctl --system daemon-reload
sudo systemctl enable meteo
sudo systemctl start meteo

Instalação do Grafana:

#!/bin/bash

version="5.4.3"
wget https://dl.grafana.com/oss/release/grafana_${version}_armhf.deb

sudo dpkg -i grafana_${version}_armhf.deb

sudo /bin/systemctl daemon-reload
sudo /bin/systemctl enable grafana-server
sudo /bin/systemctl start grafana-server

Montar uma partição ext4 para o InfluxDB:

lsblk
sudo mkfs.ext4 /dev/sda1

sudo blkid
/dev/sda1: UUID="acaa...4e9f" TYPE="ext4" PARTUUID="63...-01"

sudo nano /etc/fstab
PARTUUID=63...-01 /mnt/influxdb ext4 defaults 0 2

sudo chown influxdb:influxdb /mnt/influxdb
sudo cp -a /var/lib/influxdb/. /mnt/influxdb/

sudo nano /etc/influxdb/influxdb.conf

# under [meta]
dir = "/mnt/influxdb/meta"

# under [data]
dir = "/mnt/influxdb/data"
wal-dir = "/mnt/influxdb/wal"

sudo service influxdb restart

Ativação da autenticação no InfluDB:

influx

show users
create user iot with password '...' with all privileges
show users
exit

sudo nano /etc/influxdb/influxdb.conf

# under [http]
  enabled = true
  bind-address = ":8086"
  auth-enabled = true
  log-enabled = true
  write-tracing = false
  pprof-enabled = false
  https-enabled = false
  https-certificate = "/etc/ssl/influxdb.pem"

sudo service influxdb restart

Criação da base de dados:

influx

auth
username: iot
password: ...

show databases
create database iotdb
show databases

sudo service influxdb restart

Projetos 2016/2017

Objetivo

No intuito de obter a classificação da componente laboratorial nesta unidade curricular (até 6 valores), os estudantes deverão realizar um pequeno projeto baseado na placa ChipKIT UNO32 estudada. O Ambiente de desenvolvimento a usar pode ser qualquer um dos dois apresentados nas aulas (MPLAB X ou PlatformIO).

IMPORTANTE: De relembrar que esta componente não poderá exceder a componente dos mini testes em mais de 4 valores!

Lista de projetos

São vários os projetos passíveis de serem escolhidos por cada grupo de estudantes, não se pretendendo contudo que haja grupos com o mesmo projeto. As propostas de trabalhos são as seguintes:

  1. Reprodução de notas musicais usando a funcionalidade PWM
  2. Interface com um LED RGB e micro joystick
  3. Interface com o sensor de intensidade luminosa TSL230R
  4. Emissor e/ou recetor de sinais infravermelhos dum comando remoto duma TV
  5. Controlo dum motor passo-a-passo
  6. Interface com o módulo GPS LS20031
  7. Interface por I2C com o DAC MCP4728
  8. Interface por I2C com o DAC DAC8574
  9. Interface por I2C com o ADC MCP3424
  10. Interface por I2C com o ADC ADS1115
  11. Interface por SPI com o acelerómetro ADXL345
  12. Interface por I2C com um sensor de pressão BMP085 presente na IMU GY-80
  13. Interface por I2C com o magnetómetro MAG3110
  14. Interface por I2C com o magnetómetro HMC5883L
  15. Interface por I2C com o sensor de temperatura TMP75/175
  16. Interface por I2C com o sensor de temperatura ADT7410
  17. Interface 1-Wire com o sensor de temperatura DS18B20
  18. Interface por I2C com um display OLED 128×64 controlado pelo SSD1306
  19. Interface por SPI com um display OLED 128×64 controlado pelo SSD1306
  20. Interface por SPI com um display LCD 320×240 controlado pelo ILI9340
  21. Interface por SPI com um display LCD 84×48 Nokia 5110 (controlador PCD8544)
  22. Comunicação sem fios com os módulos NRF24L01
  23. Comunicação sem fios com módulos 433MHz
  24. Comunicação WiFi recorrendo ao módulo ESP8266
  25. Comunicação Bluetooth usando o módulo HC-05
  26. Interface com o leitor de RFID RC522
  27. Interface por I2C com um módulo ZS-042 (RTC DS3231 + EEPROM AT24C32)
  28. Interface com um cartão de memória (micro)SD
  29. Interface com o sensor de distâncias por IR GP2Y0A21YK0
  30. Interface por I2C com o sensor de distâncias por ultrassons SRF08 / SRF10

Uma procura na Internet pelo nome dos dispositivos permitirá aceder à sua datasheet!

Escolha do projeto

Os estudantes deverão comunicar ao docente a sua escolha de entre a lista acima indicada ou um projeto próprio caso ele cumpra os objetivos pretendidos. Esta escolha será realizada preenchendo um formulário até ao final do dia 4/dez. Uma vez conciliadas todas as escolhas será atribuído a cada grupo um projeto com o material necessário à sua realização.

Sessão de apresentação

A apresentação do projeto de cada grupo decorrerá numa sessão a realizar no dia 12 de Janeiro, tendo os respetivos estudantes que enviar por e-mail ([email protected]) até ao final do dia 15/jan um relatório sucinto sobre o trabalho em pdf, assim como um zip com o código fonte do projeto.

Horário

Hora Grupo Estudante Estudante
14:00 G01 Pedro Pinto Tiago Catalão
14:10 G02 Tiago Pinto Renato Ferreira
14:20 G03 António Tomás Costa Nunes Mafalda Pereira Varela
14:30 G04 Guilherme José Esteves Pelayo Hugo Miguel Malheiro de Passos Guia
14:40 G05 Francisco Fonseca Pedro Ricardo
14:50 G06 Renato Cruz Ricardo Esteves
15:00 G07 Isa Vanessa Nunes de Almeida António Pedro Rodrigues Pereira
15:10 G08 Artur Jorge Coutinho Ribeiro João Pedro Xavier Araújo
15:20 G09 Isabel Cristina Rio-Torto de Oliveira Nuno Francisco Monteiro de Barros Moreira
15:30 G10 Patrícia Sá e Sousa da Costa Ricardo de Paula Pinto Sousa Ribeiro
15:40 G11 Daniel Miranda Silva Malafaia Granhão Pedro Miguel Ramos Costa
15:50 G12 Carlos Alberto Lopes Neto Edgar dos Santos de Matos
16:30 G13 André Duarte Correia de Oliveira Nuno Miguel Rodrigues Gomes
16:40 G14 Gabriel Pinheiro Américo Duarte
16:50 G15 João Neves João Costa
17:00 G16 Anabela Reigoto Francisca Brito
17:10 G17 Ana Beatriz Cruz Marcia Sofia Alves
17:20 G18 Baltasar Aroso Pedro Costa
17:30 G19 Filipa Gomes Raimundo Nuno Fernandes Adrego
17:40 G20 João Paulo Aires da Silva Miguel André A. Tomás Ferreira de Barros
17:50 G21 Joana Whiteman Catarino Sara Serra Costa
18:00 G22 António M. S. Marques Carreiro Pedro José Ascenção Ramalho
18:10 G23 Armando Nicolau Moreno Vasco Rodrigues Arez
18:20 G24 José Ribeiro Pedro Cova

PlatformIO 2016/17

Introdução

O PlatformIO é uma plataforma para o desenvolvimento de software destinado a várias arquiteturas e várias placas nomeadamente as ChipKIT UNO32 que usaremos nas aulas.

Uma das vantagens da utilização desta plataforma é a possibilidade de se usar as funções da biblioteca Arduino que começam a ser um autêntico standard no desenvolvimento de sistema baseados em microcontroladores.

Nesta página iremos descrever o processo de instalação e criação dum primeiro projeto para o caso particular do sistema operativo Windows embora esta plataforma possa ser usada noutros sistemas operativos como o OS X e Linux.

Instalação

Previamente à instalação do PlatformIO, e porque ele foi escrito em linguagem Python, será necessário ter previamente instalada uma versão 2.7 do Python (não a versão 3). Caso se pretenda usufruir da funcionalidade “code completion” no PlatformIO será também preciso instalar o pacote CLang.

O processo de instalação começa pela descarga do ficheiros de instalação do editor Atom disponível para o sistema operativo pretendido (platformio-atom-windows.exe no caso do Windows). Uma vez executado, é iniciada a etapa de instalação do IDE (ambiente integrado de desenvolvimento) PlatformIO:

atom

Terminada esta etapa é apresentada a seguinte janela, onde deveremos escolher a opção de “Reload now”:

installed

Surgindo então a seguinte janela inicial:

platformio

Criação dum projeto

Carregando no botão “New Project” da janela inicial, faz surgir um “wizard” para criação dum novo projeto:

new

Antes de concluir o processo (carregando no botão “Initialize“, é preciso escolher:

  • a placa a usar (Selected board): no nosso caso a Digilent chipKIT UNO32
  • a pasta que albergará o projeto (Choose the directory)

Neste último caso dever-se-á situar a pasta do projeto (neste exemplo chamada blink) dentro duma das 3 pastas que foram criadas para o efeito C:\usr\Alunos\COMP\3MIEEC_Tx (dependendo da turma em causa). É importante pois evitar o uso do “Ambiente de trabalho” sob pena destas serem periodicamente apagadas!

Caso a criação dum projeto para uma determinada arquitetura de placas ocorra pela primeira vez, são instaladas todas as ferramentas necessárias (a chamada toolchain) sendo durante o processo apresentada uma mensagem, neste caso: Installing platform: microchippic32. Em futuros projetos para uma mesma placa, tal já não irá repetir-se.

Criado o projeto, a sua estrutura será apresentada no lado esquerdo da janela do PlatformIO:

project

É preciso agora criar na pasta src um novo ficheiro (blink.cpp) com o código fonte do projeto:

newfile

O código fonte a introduzir neste exemplo, destina-se a fazer piscar um LED da placa, e é o seguinte:

#include "Arduino.h"

#define LED 13

void setup() {
  pinMode(LED, OUTPUT);
}

void loop() {
  digitalWrite(LED, HIGH);
  delay(1000);
  digitalWrite(LED, LOW);
  delay(1000);
}

Segue-se a fase de compilação (Build) do código, que é iniciada carregando no primeiro icon do lado esquerdo do PlatformIO:

build

Por fim, o ficheiro contendo o binário do programa é descarregado (Upload) para a memória Flash do PIC32 da placa através do segundo ícone do lado esquerdo do PlatformIO:

upload

De notar que após carregar no botão de Upload, poderá ser necessário fazer Reset à placa. Desta forma o processo de descarga decorrerá sem percalços desde que o porto de ligação à placa esteja liberto. No final do processo, e face ao programa utilizado, o LED da placa ChipKIT irá piscar!

Projeto semaforo

Tendo em conta a dificuldade que houve na utilização dos botões (pois apresentam um funcionamento assíncrono) bem como da “variável” tempo, foi criado um módulo Python (gpio_utils.py) com classes que facilitam o uso destes elementos assim como dos LEDs:

import pigpio

class timer:
    def __init__(self, pi):
        self._pi = pi
        self.reset()
        
    def reset(self):
        self._t = self._pi.get_current_tick()
        
    def time(self):
        return self._pi.get_current_tick() - self._t

class button:
    def __init__(self, pi, pin):
        self._pi = pi
        self._pin = pin
        self._pi.set_mode(self._pin, pigpio.INPUT) 
        self._pi.callback(self._pin, pigpio.FALLING_EDGE, self._cb)
        self._h = False
    
    def _cb(self, gpio, level, tick):
        self._h = True
    
    def hitted(self):
        tmp = self._h
        self._h = False
        return tmp
    
    def state(self):
        return not self._pi.read(self._pin)

class led:
    def __init__(self, pi, pin):
        self._pi = pi
        self._pin = pin
        self._pi.set_mode(self._pin, pigpio.OUTPUT)
        self.off()
    
    def off(self):
        self._pi.write(self._pin, 0)
        
    def on(self):
        self._pi.write(self._pin, 1)

Desde logo é possível dar o primeiro passo no projeto semaforo:

import platform
import pigpio
import time
from gpio_utils import timer, button, led

if platform.uname()[4][0:3] == "arm":
    pi = pigpio.pi()
else:
    pi = pigpio.pi("10.0.0.1xx")
    
t = timer(pi)
Bp = button(pi, 23)
Bi = button(pi, 24)
Lg = led(pi, 21)
Ly = led(pi, 20)
Lr = led(pi, 16)

leave = False
while not leave:
    if Bp.hitted():
        Lg.on()
        t.reset()
    
    if Bi.hitted() or t.time() > 3000000:
        Lg.off()

    time.sleep(.05)
    leave = Bi.state() and Bp.state()

Lg.off()
Ly.off()
Lr.off()

pi.stop()

Para implementar o normal funcionamento pretendido para o semáforo, vamos usar uma abordagem já nossa conhecida de “Eletrónica Digital” que são as “máquinas de estados finitos” (FSM – Finite State Machines). Na sua versão mais simples teríamos o seguinte diagrama de transições de estados:

FSM

Optou-se por uma máquina de “Mealy” para minimizar as chamadas às funções da biblioteca pigpio que assim se fazem apenas quando das transições entre estados.

import platform
import pigpio
import time
from gpio_utils import timer, button, led

if platform.uname()[4][0:3] == "arm":
    pi = pigpio.pi()
else:
    pi = pigpio.pi("10.0.0.1xx")
    
t = timer(pi)
Bp = button(pi, 23)
Bi = button(pi, 24)
Lg = led(pi, 21)
Ly = led(pi, 20)
Lr = led(pi, 16)

# States
INI = 0
SG = 1
SY = 2
SR = 3

s = INI
leave = False
while not leave:
    if s == INI:
        ns = SG
        Lg.on()
        t.reset()
    elif s == SG:
        if t.time() > 9000000:
            ns = SY
            Lg.off()
            Ly.on()
            t.reset()
        else:
            ns = SG
    elif s == SY:
        if t.time() > 1000000:
            ns = SR
            Ly.off()
            Lr.on()
            t.reset()
        else:
            ns = SY
    elif s == SR:
        if t.time() > 5000000:
            ns = SG
            Lr.off()
            Lg.on()
            t.reset()
        else:
            ns = SR

    s = ns       

    time.sleep(.05)
    leave = Bi.state() and Bp.state()

Lg.off()
Ly.off()
Lr.off()

pi.stop()

Vamos agora adicionar a funcionalidade para antecipar o amarelo:

import platform
import pigpio
import time
from gpio_utils import timer, button, led

if platform.uname()[4][0:3] == "arm":
    pi = pigpio.pi()
else:
    pi = pigpio.pi("10.0.0.1xx")
    
t = timer(pi)
Bp = button(pi, 23)
Bi = button(pi, 24)
Lg = led(pi, 21)
Ly = led(pi, 20)
Lr = led(pi, 16)

# States
INI = 0
SG = 1
SY = 2
SR = 3

s = INI
leave = False
while not leave:
    if s == INI:
        ns = SG
        Lg.on()
        flag = False
        t.reset()
    elif s == SG:
        if Bp.hitted():
            flag = True
        if t.time() > 9000000 or flag and t.time() > 4000000:
            ns = SY
            Lg.off()
            Ly.on()
            t.reset()
        else:
            ns = SG
    elif s == SY:
        if t.time() > 1000000:
            ns = SR
            Ly.off()
            Lr.on()
            t.reset()
        else:
            ns = SY
    elif s == SR:
        if t.time() > 5000000:
            ns = SG
            Lr.off()
            Lg.on()
            flag = False
            t.reset()
        else:
            ns = SR

    s = ns       

    time.sleep(.05)
    leave = Bi.state() and Bp.state()

Lg.off()
Ly.off()
Lr.off()

pi.stop()

Finalmente é adicionado o modo intermitente:

import platform
import pigpio
import time
from gpio_utils import timer, button, led

if platform.uname()[4][0:3] == "arm":
    pi = pigpio.pi()
else:
    pi = pigpio.pi("10.0.0.1xx")
    
t = timer(pi)
Bp = button(pi, 23)
Bi = button(pi, 24)
Lg = led(pi, 21)
Ly = led(pi, 20)
Lr = led(pi, 16)

# States
INI = 0
SG = 1
SY = 2
SR = 3
INT = 4
SY1 = 5
SY0 = 6

s = INI
leave = False
while not leave:
    if s == INI:
        ns = SG
        Lg.on()
        flag = False
        t.reset()
    elif s == SG:
        if Bp.hitted():
            flag = True
        if t.time() > 9000000 or flag and t.time() > 4000000:
            ns = SY
            Lg.off()
            Ly.on()
            t.reset()
        else:
            ns = SG
    elif s == SY:
        if t.time() > 1000000:
            ns = SR
            Ly.off()
            Lr.on()
            t.reset()
        else:
            ns = SY
    elif s == SR:
        if t.time() > 5000000:
            ns = SG
            Lr.off()
            Lg.on()
            flag = False
            t.reset()
        else:
            ns = SR
            
    if s == INT:
        ns = SY1
        Ly.on()
        t.reset()
    elif s == SY1:
        if t.time() > 1000000:
            ns = SY0
            Ly.off()
            t.reset()
        else:
            ns = SY1
    elif s == SY0:
        if t.time() > 1000000:
            ns = SY1
            Ly.on()
            t.reset()
        else:
            ns = SY0
    
    if Bi.hitted():
        Lg.off()
        Ly.off()
        Lr.off()
        if s == SG or s == SY or s == SR:
            ns = INT
        if s == SY1 or s == SY0:
            ns = INI
        
    s = ns       

    time.sleep(.05)
    leave = Bi.state() and Bp.state()

Lg.off()
Ly.off()
Lr.off()

pi.stop()

 

Semáforo em Arduino

Esta é uma solução possível para o problema do Semáforo aqui proposto.

Para além da classe Button anteriormente já apresentada, nesta solução foram criadas 3 outras classes (Semaforo, Normal e Blink), todas definidas no ficheiro semaforo.h:

// Only modify this file to include
// - function definitions (prototypes)
// - include files
// - extern variable definitions
// In the appropriate section

#ifndef _semaforo_H_
#define _semaforo_H_
#include "Arduino.h"
//add your includes for the project semaforo here

//end of add your includes here
#ifdef __cplusplus
extern "C" {
#endif
void loop();
void setup();
#ifdef __cplusplus
} // extern "C"
#endif

//add your function definitions for the project semaforo here

#define Bp 12
#define Bi 11
#define Lg 3
#define Ly 5
#define Lr 6

#define S_NORMAL 0
#define S_BLINK 1

#define S_ON 0
#define S_OFF 1

#define S_LG 0
#define S_LY 1
#define S_LR 2

class Normal {
public:
    void begin();
    void proc();
private:
    int state;
    long unsigned time;
    bool flag;
};

class Blink {
public:
    void begin();
    void proc();
private:
    int state;
    long unsigned time;
};

class Semaforo {
public:
    Semaforo();
    void proc();
private:
    int state;
    Normal normal;
    Blink blink;
};

//Do not add code below this line
#endif /* _semaforo_H_ */

O ficheiro semaforo.cpp será o seguinte:

// Do not remove the include below
#include "semaforo.h"
#include "button.h"

Semaforo fsm;
Button butBi(Bi);
Button butBp(Bp);

//The setup function is called once at startup of the sketch
void setup()
{
// Add your initialization code here
    Serial.begin(115200);
}

// The loop function is called in an endless loop
void loop()
{
    butBi.proc();
    butBp.proc();
    fsm.proc();
}

Semaforo::Semaforo() {
    pinMode(Lr, OUTPUT);
    pinMode(Ly, OUTPUT);
    pinMode(Lg, OUTPUT);

    digitalWrite(Lr, LOW);
    digitalWrite(Ly, LOW);
    digitalWrite(Lg, LOW);

    state = S_NORMAL;
    normal.begin();
}

void Semaforo::proc() {
    switch (state) {
    case S_NORMAL:
        normal.proc();
        if (butBi.clicked()) {
            state = S_BLINK;
            blink.begin();
        }
        break;
    case S_BLINK:
        blink.proc();
        if (butBi.clicked()) {
            state = S_NORMAL;
            normal.begin();
        }
        break;
    }
}

void Normal::begin() {
    digitalWrite(Lg, HIGH);
    digitalWrite(Ly, LOW);
    digitalWrite(Lr, LOW);

    state = S_LG;
    flag = false;
    time = millis();
    Serial.println("LG");
}

void Normal::proc() {
    long unsigned t;

    switch (state) {
    case S_LG:
        if (butBp.clicked())
            flag = true;
        t = millis() - time;
        if ((t > 9000) or (flag and (t > 4000))) {
            time = millis();
            state = S_LY;
            digitalWrite(Lg, LOW);
            digitalWrite(Ly, HIGH);
            Serial.println("LY");
        }
        break;
    case S_LY:
        if (millis() - time > 1000) {
            time += 1000;
            state = S_LR;
            digitalWrite(Ly, LOW);
            digitalWrite(Lr, HIGH);
            Serial.println("LR");
        }
        break;
    case S_LR:
        if (millis() - time > 5000) {
            time += 5000;
            state = S_LG;
            digitalWrite(Lr, LOW);
            digitalWrite(Lg, HIGH);
            flag = false;
            Serial.println("LG");
        }
        break;
    }
}

void Blink::begin() {
    digitalWrite(Lg, LOW);
    digitalWrite(Ly, HIGH);
    digitalWrite(Lr, LOW);

    state = S_ON;
    time = millis();
    Serial.println("ON");
}

void Blink::proc() {
    switch (state) {
    case S_ON:
        if (millis() - time > 1000) {
            time += 1000;
            state = S_OFF;
            digitalWrite(Ly, LOW);
            Serial.println("OFF");
        }
        break;
    case S_OFF:
        if (millis() - time > 1000) {
            time += 1000;
            state = S_ON;
            digitalWrite(Ly, HIGH);
            Serial.println("ON");
        }
        break;
    }
}