Se o módulo ESP32 já abalou as estruturas da comunidade Maker, imagina uma placa que além do ESP32, tem também um super processador capaz de rodar algoritmos de Inteligência Artificial!
Essa placa é o Maixduino! Ela é baseada no módulo Sipeed MAIX, que usa o poderoso Kendryte K210.
Este SoC (System-on-Chip) integra audição e visão de máquina, sendo assim, uma plataforma poderosa para desenvolver produtos de inteligência artificial e IoT.
O módulo Sipeed MAIX já estava disponível a um custo muito baixo, mas a Maixduino traz todo esse poder para o mundo Arduino, tornando o desenvolvimento de soluções de ponta em IA e IoT, uma realidade para milhares de Makers.
Características:
form factor do Arduino Uno
CPU: RISC-V Dual Core 64bit
processador de rede neural de 400MHz
identificação de imagem QVGA@60FPS/VGA@30FPS
módulo ESP32 onboard - Wifi 2.4G 802.11. b/g/n e Bluetooth 4.2
porta I2S omnidirectional
microfone MEMS
conector para câmera DVP
conector para display LCD
slot de cartão micro-SD
saída DAC+PA amplificada (3W)
USB tipo C
visão de máquina baseada em rede neural convolucional
processador de microfone de alta performance para audição de máquina
suporte nas IDEs: Arduino, MaixPy, OpenMV e PlatformIO
Com essa placa você pode tirar sua aplicação de IA da nuvem, e rodar localmente em um hardware pequeno e barato, tendo assim grande desempenho e privacidade.
Veja esse vídeo do módulo Sipeed MAIX fazendo identificação de face:
Uma nova era está começando para a comunidade Maker, com uma infinidade de possibilidades, descobertas e oportunidades onde o limite é a sua imaginação!
Hoje vamos apresentar um projeto bem simples e interessante: tocar a música tema do filme Vingadores de forma polifônica.
Veja e escute esse circuito funcionando no YouTube:
É muito fácil gerar sons com Arduino utilizando a função tone:
tone(pino, frequencia, duração)
Assim você pode fazer uma série de chamadas para a função, cada uma com uma frequência e duração específica, reproduzindo desta forma uma melodia.
O problema é que com a função tone só conseguimos tocar uma nota por vez, não podendo assim, tocar melodias um pouco mais complexas.
Para resolver isso iremos utilizar a biblioteca Playtune de Len Shustek.
Essa biblioteca permite ler um stream de dados e reproduzir músicas, tocando 3 notas por vez.
Para fazer isso são utilizadas 3 interrupções, cada uma tocando uma nota por vez.
Esse projeto utiliza o Arduino Uno que tem apenas 3 interrupções, mas o Arduino Mega tem 6, podendo assim reproduzir músicas ainda mais complexas.
Você pode baixar a Playtune e ver mais detalhes do seu funcionamento no GitHub:
O circuito é bem simples: basta ligar 3 resistores de 220 ohms nos pinos 10, 11 e 12, juntar a outra ponta dos terminais e ligar diretamente em um alto-falante.
Cada um dos pinos (10, 11 e 12) estão gerando frequências diferentes e os resistores fazem a "mixagem" destes sinais para tocar no alto-falante.
Você pode ligar um led em cada uma das portas, indicando assim quando tem um sinal presente naquele canal. Essa ligação é opcional, não interferindo no funcionamento da reprodução do áudio.
Montagem em Breadboard
Esse circuito pode ser facilmente montado em uma breadboard.
É aconselhável o uso de um alto-falante, pois os buzzers normalmente utilizados com Arduino, não conseguem reproduzir a música com um volume adequado.
Você terá um resultado ainda melhor se for uma caixinha do som, mesmo sem amplificação.
Eu utilizei uma caixa de som de um kit multimídia. Ela tem um alto-falante de 4 ohms e não tem amplificação.
Um Arduino Standalone é uma montagem que reproduz o funcionamento básico de uma placa de prototipagem Arduino, com o mínimo de componentes, tornando-se a base para a montagem de um dispositivo personalizado.
Este workshop mostrará como projetar uma placa Arduino standalone, utilizando o software de CAD Fritzing.
O projeto que iremos desenvolver é um mini-videogame, que nada mais é que um o circuito básico do microcontrolador ATMega328P, um display OLED com conexão SPI e três botões: up, down e fire.
Não precisamos utilizar todos os componentes presentes em uma placa Arduino padrão. Vamos precisar apenas dos componentes básicos:
microcontrolador ATMega328P
Cristal de 16 MHz
Capacitores para o cristal
botão de reset
resistor do reset
regulador de tensão 5V
capacitores para o regulador de tensão
diodo contra inversão de polaridade
led On
led pino 13
resistores dos leds
Diagrama Esquemático
Segue abaixo o diagrama esquemático do circuito básico, acrescido com os componentes adicionais, necessários para o projeto:
conector para o display OLED
conector FDTI para transferência do firmware
botões de acionamento do jogo
Lista dos Componentes:
Code
Component
U1
ATMega328p (com bootloader)
7805 5V
LM7805 - regulador de voltagem
Btn1
Push button
Btn2
Push button
Btn3
Push button
Reset
Push button
C1
22pF - capacitor cerâmico
C2
22pF - capacitor cerâmico
C3
100nF - capacitor cerâmico
C4
10µF- capacitor eletrolítico 16V
C5
10µF- capacitor eletrolítico 16V
D1
1N4001/1N4007 - diodo retificador
D13
Red 3mm -LED
On
Red 3mm LED
Dc_In
Jack
FDTI
Header fêmea de 6 pinos
OLED
Header fêmea de 7 pinos para display OLED com conexão SPI - pinos gnd, vdd, sck, sda, res, dc, cs
R1
10kΩ Resistor
R2
10kΩ Resistor
R3
4.7kΩ - resistor
R4
10kΩ - resistor
R5
10kΩ - resistor
R6
10kΩ - resistor
XTAL
Cristal 16Mhz - perfil baixo
Layout dos Componentes
Esse é o layout dos componentes na placa de 5cm X 5cm:
Layout com Labels
Esse é o layout dos componentes com os labels:
Trilhas
Segue abaixo o desenho das trilhas.
A espessura de trilhas utilizada foi de 12 mil.
Visão com legendas
Visão sem legendas
Visão Final
Essa é a versão final do desenho da placa, já com os labels dos componentes:
Placa confeccionada em casa
A placa abaixo foi feita através do processo de transferência de toner:
Placa feita em fábrica profissional
Placas feitas em fábrica profissional na China:
Obs: ao final do workshop, todos os participantes receberão uma placa igual à da foto. Esse lote tem um erro de projeto, que deve ser corrigido na montagem fazendo uma união com solda dos pinos 18 e 19 do AtMega328P (pinos digitais D12 e D13). Veja na foto abaixo:
Montagem final
Placas finalizadas, com todos os componentes soldados:
O jogo utilizado foi o SpaceTrash, que é um exemplo que acompanha a biblioteca U8g2.
Faça a instalação da biblioteca utilizando o menu "Incluir biblioteca / Gerenciar bibliotecas":
Abra o exemplo SpaceTrace e faça o upload para o AtMega328P, utilizando o adaptador FDTI:
A família de placas MBZ Arduino aumentou!
A nova integrante é a MBZ Pro Mega RF Edition, que traz como destaque suporte para o módulo de comunicação wireless NRF24L01 da Nordic Semiconductor.
Este módulo é um transceiver (transmissor/receptor) que trabalha na faixa 2.4GHz ISM (Industrial, Scientific and Medical), e é destinado a projetos de periféricos de computadores, gaming, esporte/fitness, brinquedos e produtos eletrônicos de consumo.
A MBZ RF também tem uma área de prototipagem que permite customizar a placa, incluindo novas funcionalidades através de módulos e componentes.
No dia 31 de março aconteceu em Cuiabá o Arduino Day Univag 2018. Centenas de pessoas estiveram no Centro Universitário Univag para compartilhar ideias e experiências sobre Arduino e o mundo maker.
O evento organizado pela Univag e pelos canais Arduino Brasil e Eletrônica Fácil, contou com a presença de makers de renome como: Rodolpho Oliveira, Nascimento Júnior, Waldyr Reis, Alvaro Viebrantz, Fábio Souza, Gedeane Kenshima e eu Marcelo Maximiano, que recebi com imensa alegria o convite de participar desse evento grandioso.
Eu apresentei uma palestra com o tema "Como transformar um protótipo com Arduino em um produto final" e uma oficina prática "IoT - Comunicação entre Máquinas", que apresento neste artigo.
IOT - Comunicação entre máquinas
O objetivo da oficina era mostrar uma implementação simples de IoT (Internet das Coisas), onde um Arduino comandasse remotamente um motor de passo.
O diagrama abaixo mostra a implementação onde um Arduino envia comandos (definidos por um protocolo simples) via comunicação serial para um ESP8266, esse se conecta a um broker MQTT e publica uma mensagem com esse comando no feed "motor". O ESP8266 no módulo receptor, faz subscrição do mesmo tópico, e assim que recebe a mensagem, a envia via comunicação serial para o Arduino que comanda através do driver de motor ULN2003, um motor de passo modelo 28BYJ-48.
Para simplificar o exercício, utilizamos placas MBZ Wifi, pela facilidade de ter o Arduino integrado com o ESP8266. Além disso, no módulo receptor, o ULN2003 foi integrado à placa, ficando assim uma montagem única.
Protocolo de Comando do Motor
A mensagem de comando do motor segue um protocolo simples, definido para esse exercício, composto por 5 comandos:
I - Id do usuário S - velocidade de movimento do motor. Valores válidos: 10-60 R - girar para a direita X graus. Valores válidos: 1-360 L - girar para a esquerda X graus. Valores válidos: 1-360 P - pausa X milisegundos. Valores válidos: 1-2000
Desta forma uma sequencia complexa de movimentos pode ser enviada em uma única transmissão para o módulo receptor, que fará o parsing da mensagem e executará comando a comando a sequencia de movimentos. Exemplo: I:3 S:20 R:180 P:500 L:180 S:60 R:360 ID 3, velocidade 20, gira para a direita 180 graus, pausa por 500ms, gira para a esquerda 180 graus, aumenta a velocidade para 60 e gira para a direita 360 graus.
Criar Feed no serviço IoT
Para poder publicar os dados na nuvem, será necessário criar uma conta e configurar conforme detalhado abaixo: 1) crie uma conta no site iot.adafruit.com 2) crie um feed com o nome "motor"
Programas
Seguem abaixo os programas, numerados conforme o diagrama acima:
Lembre-se de instalar a biblioteca "Adafruit MQTT Library"
Módulo Emissor:
1) Arduino: envia o comando para o ESP8266
2) ESP8266: recebe o comando e envia para o MQTT broker
Módulo Receptor:
3) ESP8266: faz subscrição no MQTT broker e envia o comando para o Arduino
4) Arduino: recebe o comando e faz a movimentação do motor de passo
Programa 1 - para rodar no ATMega328P: send_atmega.ino
/*******************************************************************
MBZ MQTT example (ATMEGA328P)
-----------------------------
Este programa envia comandos para girar um motor de passo para
o módulo ESP8266.
O ESP8266 recebe os dados e os envia o serviço de IOT da Adafruit
via protocolo MQTT (Message Queuing Telemetry Transport
********************************************************************/
#include <SoftwareSerial.h>
#define rxPin 2
#define txPin 3
SoftwareSerial EspSerial(rxPin, txPin); // RX, TX
#define PIN_ENABLE_ESP8266 4
void setup() {
// seta a velocidade das portas seriais
Serial.begin(19200);
EspSerial.begin(19200);
// inicializa o ESP8266
Serial.println("Inicializando o ESP8266");
pinMode(PIN_ENABLE_ESP8266, OUTPUT);
digitalWrite(PIN_ENABLE_ESP8266, LOW);
delay(200);
digitalWrite(PIN_ENABLE_ESP8266, HIGH);
delay(1000);
String motorCommand = "I:3 S:20 R:180 P:500 L:180 S:60 R:360 ";
EspSerial.print(motorCommand);
}
void loop() {
}
Programa 2 - para rodar no ESP8266: send_esp.ino
/*******************************************************************
MBZ MQTT example (ESP8266)
-----------------------------
Este programa recebe os dados uma sequencia de comandos para
para girar um motor de passo, e os envia para o serviço
IOT da Adafruit via protocolo MQTT
********************************************************************/
#include <ESP8266WiFi.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"
#define SSID "redewifi" // id do roteador WIFI
#define PWD "senha" // senha do roteador WIFI
#define SERVER "io.adafruit.com" // servidor MQTT
#define PORT 1883 // porta do servidor
#define USR "AIO_USER" // usuário do IO Adafruit
#define KEY "AIO_KEY" // chave de acesso do IO Adafruit
WiFiClient client;
Adafruit_MQTT_Client mqtt(&client, SERVER, PORT, USR, KEY);
Adafruit_MQTT_Publish MOTOR = Adafruit_MQTT_Publish(&mqtt, USR "/feeds/motor"); // feed 1: luz
String serialData;
void setup() {
Serial.begin(19200);
// Conecta no WIFI
Serial.println();
Serial.print("Conectando no WIFI: ");
Serial.println(SSID);
WiFi.begin(SSID, PWD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi conectado");
Serial.print("IP: ");
Serial.println(WiFi.localIP());
Serial.println();
}
void loop() {
if (getSerialData()) {
if (mqtt.connect() == 0) {
char buff[100];
serialData.toCharArray(buff,100);
// envia dados para o servidor MQTT
MOTOR.publish(buff);
}
}
serialData = "";
delay(100);
}
bool getSerialData() {
bool ret = false;
if (Serial.available()) {
// lê porta serial
serialData = Serial.readString();
}
if (!serialData.equals("")) {
ret = true;
}
return ret;
}
int getValue(String str, String tk) {
String buff = "";
int p0, p1;
p0 = str.indexOf(tk);
if (p0 != -1) {
p0 = str.indexOf(":", p0) + 1;
p1 = str.indexOf(";", p0);
buff = str.substring(p0, p1);
}
return buff.toInt();
}
void MQTT_connect() {
int8_t ret;
// Stop if already connected.
if (mqtt.connected()) {
return;
}
Serial.print("Connecting to MQTT... ");
uint8_t retries = 3;
while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
Serial.println(mqtt.connectErrorString(ret));
Serial.println("Retrying MQTT connection in 5 seconds...");
mqtt.disconnect();
delay(5000); // wait 5 seconds
retries--;
if (retries == 0) {
// basically die and wait for WDT to reset me
while (1);
}
}
Serial.println("MQTT Connected!");
}
Programa 3 - para rodar no ESP8266: rec_esp.ino
/********************************************************************
MBZ MQTT example (ESP8266)
-----------------------------
Este programa faz a subscrição do feed motor e quando
recebe a mensagem, a envia para o Arduino
*********************************************************************/
#include <ESP8266WiFi.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"
#define SSID "redewifi" // id do roteador WIFI
#define PWD "senha" // senha do roteador WIFI
#define SERVER "io.adafruit.com" // servidor MQTT
#define PORT 1883 // porta do servidor
#define USR "AIO_USER" // usuário do IO Adafruit
#define KEY "AIO_KEY" // chave de acesso do IO Adafruit
WiFiClient client;
Adafruit_MQTT_Client mqtt(&client, SERVER, PORT, USR, KEY);
Adafruit_MQTT_Subscribe motor = Adafruit_MQTT_Subscribe(&mqtt, USR "/feeds/motor");
void setup() {
Serial.begin(19200);
// Conecta no WIFI
Serial.println();
Serial.print("Conectando no WIFI: ");
Serial.println(SSID);
WiFi.begin(SSID, PWD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi conectado");
Serial.print("IP: ");
Serial.println(WiFi.localIP());
Serial.println();
// subscreve o feed motor
mqtt.subscribe(&motor);
}
void loop() {
// conecta no servidor
MQTT_connect();
// verifica se há dados
Adafruit_MQTT_Subscribe *subscription;
while ((subscription = mqtt.readSubscription(5000))) {
if (subscription == &motor) {
Serial.print((char *)motor.lastread);
}
}
delay(100);
}
void MQTT_connect() {
int8_t ret;
// Stop if already connected.
if (mqtt.connected()) {
return;
}
Serial.print("Connecting to MQTT... ");
uint8_t retries = 3;
while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
Serial.println(mqtt.connectErrorString(ret));
Serial.println("Retrying MQTT connection in 5 seconds...");
mqtt.disconnect();
delay(5000); // wait 5 seconds
retries--;
if (retries == 0) {
// basically die and wait for WDT to reset me
while (1);
}
}
Serial.println("MQTT Connected!");
}
Programa 4 - para rodar no ATMega328P: rec_atmega.ino
/*******************************************************************
MBZ MQTT example (ATMega328P)
-----------------------------
Este programa recebe a mensagem do ESP8266 e comanda o motor
********************************************************************/
#include <Stepper.h>
#include <Softwareserial.h>
#define PIN_ENABLE_ESP8266 4
#define rxPin 2
#define txPin 3
SoftwareSerial EspSerial(rxPin, txPin); // RX, TX
const int stepsPerRevolution = 512;
Stepper myStepper(stepsPerRevolution, 8, 10, 9, 11);
void setup()
{
// seta a velocidade das portas seriais
Serial.begin(19200);
EspSerial.begin(19200);
// inicializa o ESP8266
Serial.println("Inicializando o ESP8266");
pinMode(PIN_ENABLE_ESP8266, OUTPUT);
digitalWrite(PIN_ENABLE_ESP8266, LOW);
delay(200);
digitalWrite(PIN_ENABLE_ESP8266, HIGH);
delay(5000);
}
void loop()
{
String st = "";
st = getSerialData(5000);
if (st != "") {
Serial.print("Motor Cmd = ");
Serial.println(st);
processCmd(st);
}
}
void processCmd(String cmd) {
int p = 0;
int ln = 0;
int id = 0;
int p0 = 0;
int p1 = 0;
int value = 0;
String ch = "";
String buff = "";
// exemplo
// I:3 S:30 R:10 S:50 L:30 P:500 S:60 R:180
cmd.trim();
cmd.toUpperCase();
ln = cmd.length();
while (p < ln) {
ch = cmd.substring(p, p + 1);
if ((ch == "I") || (ch == "S") || (ch == "R") || (ch == "L") || (ch == "P")) {
p0 = cmd.indexOf(":", p) + 1;
p1 = cmd.indexOf(" ", p0);
if (p1 == -1) {
p1 = ln;
}
buff = cmd.substring(p0, p1);
value = buff.toInt();
p = p1;
if (ch == "I") {
id = value;
}
if (ch == "S") {
// limita a velocidade: 10 - 60
if (value < 10) {
value = 10;
}
if (value > 60) {
value = 60;
}
myStepper.setSpeed(value);
}
if (ch == "R") {
turnMotor(value, 1);
}
if (ch == "L") {
turnMotor(value, 0);
}
if (ch == "P") {
// limita a pausa: 1 - 2000
if (value < 1) {
value = 1;
}
if (value > 2000) {
value = 2000;
}
delay(value);
}
}
p++;
}
}
void turnMotor(long degrees, int direction) {
long steps;
// pega o valor absoluto
degrees = abs(degrees);
// converte de graus para passos
steps = (2048 * degrees) / 360;
// se a direcao for esquerda, deixa steps negativo
if (direction == 0) { // girar para a esquerda
steps = steps * -1;
}
myStepper.step(steps);
}
int getValue(String str, String tk) {
String buff = "";
int p0, p1;
p0 = str.indexOf(tk);
if (p0 != -1) {
p0 = str.indexOf(":", p0) + 1;
p1 = str.indexOf(";", p0);
buff = str.substring(p0, p1);
}
return buff.toInt();
}
String getSerialData(const int timeout)
{
String strBuffer = "";
long int time = millis();
while ( (time + timeout) > millis())
{
if (EspSerial.available() > 0)
{
strBuffer = EspSerial.readString();
break;
}
}
return strBuffer;
}