Pular para o conteúdo principal

Multiplexação de Pinos com Seeed Studio XIAO RA4M1

Digital

O XIAO RA4M1 possui até 11 pinos GPIO regulares, 6 pinos analógicos e 8 portas de IO reutilizáveis. Neste exemplo, usaremos o XIAO RA4M1, a placa de expansão XIAO e um relé para demonstrar como usar diferentes pinos digitais para leitura e escrita.

Preparação de Hardware

Seeed Studio XIAO R4M1Seeed Studio Expansion Base for XIAO with Grove OLEDGrove - Relay

Instale o XIAO RA4M1 ou Sense na placa de expansão e conecte o relé à interface A0/D0 da placa de expansão através de um cabo Grove. Por fim, conecte o XIAO ao computador por meio de um cabo USB-C.

Implementação de Software

Neste exemplo, vamos implementar o controle do estado ligado/desligado de um relé usando um botão conectado à placa de expansão XIAO. Quando o botão for pressionado, o relé liga, e quando o botão for solto, o relé desliga.

const int buttonPin = D1;     // the number of the pushbutton pin
int buttonState = 0; // variable for reading the pushbutton status
const int relayPin = D0;

void setup() {
// initialize the Relay pin as an output:
pinMode(relayPin, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT_PULLUP);
}

void loop() {
// read the state of the pushbutton value:
buttonState = digitalRead(buttonPin);

// check if the pushbutton is pressed. If it is, the buttonState is HIGH:
if (buttonState == HIGH) {
// turn Relay on:
digitalWrite(relayPin, HIGH);
} else {
// turn Relay off:
digitalWrite(relayPin, LOW);
}
}

Se tudo correr bem, após o upload do programa, você deverá ver o seguinte efeito.

Digital como PWM

Todos os pinos GPIO do XIAO RA4M1 suportam saída PWM. Portanto, você pode usar qualquer pino para gerar PWM para ajustar o brilho de luzes, controlar servos e outras funções.

Preparação de Hardware

Seeed Studio XIAO RA4M1Seeed Studio Expansion Base for XIAO with Grove OLEDGrove - Variable Color LED

Instale o XIAO RA4M1 ou Sense na placa de expansão e, em seguida, conecte o Variable Color LED à interface A0/D0 da placa de expansão usando um cabo Grove. Por fim, conecte o XIAO ao seu computador via cabo USB-C.

Implementação de Software

Neste exemplo, demonstraremos como usar a saída PWM para controlar o brilho de uma luz.

int LED_pin = D0;    // LED connected to digital pin 10

void setup() {
// declaring LED pin as output
pinMode(LED_pin, OUTPUT);
}

void loop() {
// fade in from min to max in increments of 5 points:
for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 3) {
// sets the value (range from 0 to 255):
analogWrite(LED_pin, fadeValue);
// wait for 30 milliseconds to see the dimming effect
delay(30);
}

// fade out from max to min in increments of 5 points:
for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 3) {
// sets the value (range from 0 to 255):
analogWrite(LED_pin, fadeValue);
// wait for 30 milliseconds to see the dimming effect
delay(30);
}
}

Se o programa for executado com sucesso, você verá o seguinte efeito.

Analógico

A placa de desenvolvimento XIAO RA4M1 possui ADC de até 14 bits para leitura de alta resolução de valores de sensores analógicos, o que pode nos ajudar a ler valores mais precisos. O conversor analógico‑digital (ADC) em uma placa de desenvolvimento XIAO RA4M1, por padrão, tem a resolução definida em 10 bits, que pode ser alterada para 12 bits e 14 bits para melhorar a precisão das leituras analógicas.

Dados detalhados por precisão do ADC

  • 10-bit : 0~1024
  • 12-bit : 0~4096
  • 14-bit : 0~16383

Em seguida, escolheremos dois sensores para refletir as características do ADC.

Preparação de Hardware

Seeed Studio XIAO RA4M1Grove-Variable Color LEDGrove-Rotary Angle Sensor Seeed Studio Grove Base for XIAO

Implementação de Software

#define ADC_Bit_Fourteen 14
#define ADC_Bit_Twelve 12
#define ADC_Bit_Ten 10

const int analogInPin = A1; // Analog input pin that the potentiometer is attached to
const int analogOutPin = 9; // Analog output pin that the LED is attached to

int sensorValue = 0; // value read from the pot
int outputValue = 0; // value output to the PWM (analog out)

void setup() {

Serial.begin(115200);
// Ten_Bite_ADC_Config(); // 10bit
// Twelve_Bite_ADC_Config(); // 12bit
Fourteen_Bite_ADC_Config(); // 14bit

}

void loop() {
sensorValue = analogRead(analogInPin);
outputValue = map(sensorValue, 0, 4095, 0, 255);
analogWrite(analogOutPin, outputValue);

Serial.print("sensor = ");
Serial.print(sensorValue);
Serial.print("\t output = ");
Serial.println(outputValue);
delay(100);
}

void Ten_Bite_ADC_Config() {
analogReadResolution(ADC_Bit_Ten);
}

void Twelve_Bite_ADC_Config() {
analogReadResolution(ADC_Bit_Twelve);
}

void Fourteen_Bite_ADC_Config() {
analogReadResolution(ADC_Bit_Fourteen);
}

Se tudo correr bem, após enviar o programa, você deverá ver o seguinte efeito.

Serial

Ao trabalhar com a Arduino IDE, a comunicação Serial é uma parte essencial de muitos projetos. Para usar Serial na Arduino IDE, você precisa começar abrindo a janela Serial Monitor. Isso pode ser feito clicando no ícone Serial Monitor na barra de ferramentas ou pressionando o atalho Ctrl+Shift+M.

Uso geral

Algumas das funções Serial mais comumente usadas incluem:

  • Serial.begin() -- que inicializa a comunicação em uma taxa de baud especificada;
  • Serial.print() -- que envia dados para a porta Serial em um formato legível;
  • Serial.write() -- que envia dados binários para a porta Serial;
  • Serial.available() -- que verifica se há algum dado disponível para ser lido da porta Serial;
  • Serial.read() -- que lê um único byte de dados da porta Serial;
  • Serial.flush() -- que aguarda a conclusão da transmissão dos dados seriais de saída.

Usando essas funções Serial, você pode enviar e receber dados entre a placa Arduino e o seu computador, o que abre muitas possibilidades para criar projetos interativos.

Aqui está um programa de exemplo:

void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
}

void loop() {
// send data to the serial port
Serial.println("Hello World!");

// read data from the serial port
if (Serial.available() > 0) {
// read the incoming byte:
char incomingByte = Serial.read();
// print the incoming byte to the serial monitor:
Serial.print("I received: ");
Serial.println(incomingByte);
}

// wait for a second before repeating the loop
delay(1000);
}

Uso do Serial1

De acordo com os diagramas de pinos do XIAO RA4M1 acima para parâmetros específicos, podemos observar que existem os pinos TX e RX. Isso é diferente da comunicação serial padrão, mas o uso também é muito semelhante, exceto que alguns parâmetros precisam ser adicionados. Então, a seguir, usaremos os pinos expostos pelo chip para comunicação serial.


#define BAUD 115200

void setup() {
Serial1.begin(BAUD);
}

void loop() {
if(Serial1.available() > 0)
{
char incominByte = Serial1.read();
Serial1.print("I received : ");
Serial1.println(incominByte);
}
delay(1000);
}

Uso do Software Serial

#include <SoftwareSerial.h>

SoftwareSerial mySerial(2, 3); // RX, TX

void setup() {
// initialize serial communication
Serial.begin(9600);
while (!Serial);

// initialize software serial
mySerial.begin(9600);
}

void loop() {
// read data from software serial
if (mySerial.available()) {
char data = mySerial.read();
Serial.print("Received data: ");
Serial.println(data);
}

// write data to software serial
mySerial.print("Hello World!");

// wait for a second before repeating the loop
delay(1000);
}

Neste programa, primeiro incluímos a biblioteca SoftwareSerial.h para usar a serial por software. Em seguida, criamos um novo objeto SoftwareSerial chamado mySerial usando os pinos 2 e 3 como RX e TX, respectivamente.

Na função setup(), inicializamos tanto a serial de hardware (Serial.begin()) quanto a serial por software (mySerial.begin()).

Na função loop(), usamos a função mySerial.available() para verificar se há algum dado disponível para ser lido da serial por software. Se houver, lemos o byte recebido usando a função mySerial.read() e o armazenamos em uma variável chamada data. Em seguida, usamos as funções Serial.print() e Serial.println() para imprimir "Received data: " seguida do valor de data na serial de hardware.

Também usamos a função mySerial.print() para escrever "Hello World!" na serial por software. Isso enviará os dados do XIAO para o dispositivo conectado à porta serial por software.

Por fim, adicionamos uma função delay() para aguardar um segundo antes de repetir o loop.

IIC

O XIAO RA4M1 possui uma interface I2C que pode ser usada para transmissão e análise de dados de muitos sensores, bem como para usar algumas telas OLED.

Preparação de hardware

Seeed Studio XIAO RA4M1Seeed Studio Expansion Base for XIAO with Grove OLED

O display OLED na placa de expansão XIAO usa o protocolo I2C e é conectado à interface I2C do XIAO através do circuito I2C na placa. Portanto, podemos conectar diretamente o XIAO à placa de expansão e programá-lo para exibir conteúdo na tela.

Implementação de software

Este exemplo apresenta como usar o display OLED na Seeed Studio Expansion Base para XIAO RA4M1.

Passo 1. Instale o Seeed Studio XIAO RA4M1 na placa de expansão e depois conecte o cabo Type-C

Passo 2. Instale a biblioteca u8g2

Passo 3. Copie o código e cole na Arduino IDE e depois envie-o

#include <Arduino.h>
#include <U8x8lib.h>
#include <Wire.h>

U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE); // OLEDs without Reset of the Display

void setup(void) {
u8x8.begin();
u8x8.setFlipMode(1); // set number from 1 to 3, the screen word will rotary 180
}

void loop(void) {
u8x8.setFont(u8x8_font_chroma48medium8_r);
u8x8.setCursor(0, 0);
u8x8.print("i'm XIAO RA4M1");
}

Nas primeiras linhas do código, incluímos as bibliotecas necessárias, como Arduino.h, U8x8lib.h e Wire.h. A biblioteca U8x8lib.h fornece funções para controlar o display OLED, e a biblioteca Wire.h fornece funções para comunicação I2C.

Na função setup(), inicializamos o display OLED usando a função u8x8.begin(). Também definimos o modo de inversão do display usando a função u8x8.setFlipMode() para girar a tela em 180 graus.

Na função loop(), definimos a fonte usando a função u8x8.setFont() e especificamos a posição do cursor no display usando a função u8x8.setCursor(). Por fim, usamos a função u8x8.print() para exibir a string "Hello World!" no display OLED.

Se você enviar um programa para o XIAO RA4M1, verá conteúdo exibido na tela OLED na placa de expansão.

SPI

O chip RA4M1 integra múltiplos periféricos, incluindo uma interface SPI que pode ser usada para conectar dispositivos SPI externos, como memória flash, displays, sensores e muito mais. O XIAO RA4M1 também suporta modo de transferência SPI em alta velocidade, que pode atingir uma taxa máxima de transferência SPI de 80 MHz, atendendo às necessidades de transferência de dados da maioria dos dispositivos SPI.

Preparação de hardware

Seeed Studio XIAO RA4M1Grove - OLED Display 1.12 (SH1107) V3.0 - SPI/IIC

Após preparar o hardware como mencionado acima, use fios jumper para conectar a interface SPI do XIAO e do OLED. Consulte o diagrama a seguir para o método de fiação.

Implementação de Software

Em seguida, usaremos o seguinte programa como exemplo para apresentar como usar a interface SPI para controlar a exibição da tela OLED.

Instale a biblioteca u8g2.

#include <Arduino.h>
#include <U8g2lib.h>
#include <SPI.h>
#include <Wire.h>

U8G2_SH1107_128X128_1_4W_HW_SPI u8g2(U8G2_R3, /* cs=*/ D7, /* dc=*/ D4, /* reset=*/ D5);

void setup(void) {
u8g2.begin();
}

void loop(void) {
u8g2.firstPage();

do {
u8g2.setFont(u8g2_font_luBIS08_tf);
u8g2.drawStr(0,24,"Hello Seeed!");
} while ( u8g2.nextPage() );
}

Na função setup(), a classe U8G2_SH1107_128X128_1_4W_HW_SPI é instanciada com os argumentos de construtor apropriados que especificam os pinos usados para chip select (cs), dados/comando (dc) e reset. Em seguida, a função u8g2.begin() é chamada para inicializar o display.

Na função loop(), o display é atualizado com novo conteúdo usando as funções u8g2.firstPage(), u8g2.setFont() e u8g2.drawStr(). A função u8g2.firstPage() configura o buffer de exibição para escrita, enquanto u8g2.nextPage() exibe o conteúdo atualizado. O loop do-while garante que o conteúdo seja exibido continuamente até que o programa seja interrompido.

No geral, este código demonstra como usar a biblioteca U8g2 para controlar um display OLED e exibir texto nele.

CAN (Placa de Expansão XIAO CAN Bus)

Preparação de Hardware

Seeed Studio XIAO RA4M1Placa de Expansão XIAO CAN Bus

Etapa 1. Prepare duas CAN Bus Breakout Board e XIAO RA4M1

Etapa 2. Insira esses dois XIAO RA4M1 separadamente na CAN Bus Breakout Board

Etapa 3. Prepare a conexão com fio DuPont

Preparação de Software

Nós fornecemos uma biblioteca Arduino para a placa MCP2515.


A biblioteca inclui vários exemplos, incluindo:

  • OBDII-PIDs - recuperar dados da interface OBD-II
  • send - enviar um frame para o barramento CAN
  • recv - receber um frame do barramento CAN
  • set_mask_filter_recv - receber um frame do barramento CAN com configurações de máscara e filtro

Implementação de Software

dica

Não é permitido ligar simultaneamente e fazer o download de programas para dois XIAO RA4M1, pois isso resultará em erros ao fazer o download pela porta serial. Depois de fazer o download para um, desconecte-o, então ligue o outro XIAO RA4M1 para baixar o programa e, finalmente, ligue-os ao mesmo tempo para verificar a mensagem da porta serial

Código de Escrita CAN


/* send a frame from can bus

CAN Baudrate,

#define CAN_5KBPS 1
#define CAN_10KBPS 2
#define CAN_20KBPS 3
#define CAN_25KBPS 4
#define CAN_31K25BPS 5
#define CAN_33KBPS 6
#define CAN_40KBPS 7
#define CAN_50KBPS 8
#define CAN_80KBPS 9
#define CAN_83K3BPS 10
#define CAN_95KBPS 11
#define CAN_100KBPS 12
#define CAN_125KBPS 13
#define CAN_200KBPS 14
#define CAN_250KBPS 15
#define CAN_500KBPS 16
#define CAN_666KBPS 17
#define CAN_1000KBPS 18
*/

#include <mcp_can.h>
#include <SPI.h>

/* Please modify SPI_CS_PIN to adapt to your board.

CANBed V1 - 17
CANBed M0 - 3
CAN Bus Shield - 9
CANBed 2040 - 9
CANBed Dual - 9
OBD-2G Dev Kit - 9
OBD-II GPS Kit - 9
Hud Dev Kit - 9

Seeed Studio CAN-Bus Breakout Board for XIAO and QT Py - D7
*/

#define SPI_CS_PIN D7

MCP_CAN CAN(SPI_CS_PIN); // Set CS pin

void setup()
{
Serial.begin(115200);
while(!Serial);

// below code need for OBD-II GPS Dev Kit Atemga32U4 version
// pinMode(A3, OUTPUT);
// digitalWrite(A3, HIGH);

// below code need for OBD-II GPS Dev Kit RP2040 version
// pinMode(12, OUTPUT);
// digitalWrite(12, HIGH);

while (CAN_OK != CAN.begin(CAN_500KBPS)) // init can bus : baudrate = 500k
{
Serial.println("CAN BUS FAIL!");
delay(100);
}
Serial.println("CAN BUS OK!");
}

unsigned char stmp[8] = {0, 1, 2, 3, 4, 5, 6, 7};
void loop()
{
CAN.sendMsgBuf(0x00, 0, 8, stmp);
delay(100); // send data per 100ms
}

// END FILE

Código de Leitura CAN

/*  receive a frame from can bus

CAN Baudrate,

#define CAN_5KBPS 1
#define CAN_10KBPS 2
#define CAN_20KBPS 3
#define CAN_25KBPS 4
#define CAN_31K25BPS 5
#define CAN_33KBPS 6
#define CAN_40KBPS 7
#define CAN_50KBPS 8
#define CAN_80KBPS 9
#define CAN_83K3BPS 10
#define CAN_95KBPS 11
#define CAN_100KBPS 12
#define CAN_125KBPS 13
#define CAN_200KBPS 14
#define CAN_250KBPS 15
#define CAN_500KBPS 16
#define CAN_666KBPS 17
#define CAN_1000KBPS 18

CANBed V1: https://www.longan-labs.cc/1030008.html
CANBed M0: https://www.longan-labs.cc/1030014.html
CAN Bus Shield: https://www.longan-labs.cc/1030016.html
OBD-II CAN Bus GPS Dev Kit: https://www.longan-labs.cc/1030003.html
*/

#include <SPI.h>
#include "mcp_can.h"

/* Please modify SPI_CS_PIN to adapt to your board.

CANBed V1 - 17
CANBed M0 - 3
CAN Bus Shield - 9
CANBed 2040 - 9
CANBed Dual - 9
OBD-2G Dev Kit - 9
OBD-II GPS Kit - 9
Hud Dev Kit - 9

Seeed Studio CAN-Bus Breakout Board for XIAO and QT Py - D7
*/


#define SPI_CS_PIN D7

MCP_CAN CAN(SPI_CS_PIN); // Set CS pin


void setup()
{
Serial.begin(115200);
while(!Serial);

// below code need for OBD-II GPS Dev Kit Atemga32U4 version
// pinMode(A3, OUTPUT);
// digitalWrite(A3, HIGH);

// below code need for OBD-II GPS Dev Kit RP2040 version
// pinMode(12, OUTPUT);
// digitalWrite(12, HIGH);

while (CAN_OK != CAN.begin(CAN_500KBPS)) // init can bus : baudrate = 500k
{
Serial.println("CAN BUS FAIL!");
delay(100);
}
Serial.println("CAN BUS OK!");
}


void loop()
{
unsigned char len = 0;
unsigned char buf[8];

if(CAN_MSGAVAIL == CAN.checkReceive()) // check if data coming
{
CAN.readMsgBuf(&len, buf); // read data, len: data length, buf: data buf

unsigned long canId = CAN.getCanId();

Serial.println("-----------------------------");
Serial.print("Get data from ID: ");
Serial.println(canId, HEX);

for(int i = 0; i<len; i++) // print the data
{
Serial.print(buf[i], HEX);
Serial.print("\t");
}
Serial.println();
}
}

// END FILE

dica

Neste exemplo, você precisa soldar um dos pinos do terminal P1 da placa de breakout do barramento CAN. Só então qualquer velocidade poderá ser usada; caso contrário, você só poderá usar abaixo de 125 de baudrate CAN.

CAN(Outro transceptor)

Gostaríamos de agradecer ao Arduino por fornecer os tutoriais e o código.

Preparação de hardware

O protocolo CAN exige que a extremidade de envio receba a mensagem que envia. Simplesmente conectar TX e RX não é suficiente para completar a comunicação; é necessário conectar um transceptor para a comunicação. Aqui, usamos o módulo divisor SN65HVD230 oficial da Arduino.

3.3 VGNDD9(CANRX0)D10 (CANTX0)
VCCGNDCANRXCANTX

Preparação de software

Código de escrita CAN

/*
CANWrite

Write and send CAN Bus messages

See the full documentation here:
https://docs.arduino.cc/tutorials/uno-r4-wifi/can
*/

/**************************************************************************************
* INCLUDE
**************************************************************************************/

#include <Arduino_CAN.h>

/**************************************************************************************
* CONSTANTS
**************************************************************************************/

static uint32_t const CAN_ID = 0x20;

/**************************************************************************************
* SETUP/LOOP
**************************************************************************************/

void setup()
{
Serial.begin(115200);
while (!Serial) { }

if (!CAN.begin(CanBitRate::BR_250k))
{
Serial.println("CAN.begin(...) failed.");
for (;;) {}
}
}

static uint32_t msg_cnt = 0;

void loop()
{
/* Assemble a CAN message with the format of
* 0xCA 0xFE 0x00 0x00 [4 byte message counter]
*/
uint8_t const msg_data[] = {0xCA,0xFE,0,0,0,0,0,0};
memcpy((void *)(msg_data + 4), &msg_cnt, sizeof(msg_cnt));
CanMsg const msg(CanStandardId(CAN_ID), sizeof(msg_data), msg_data);

/* Transmit the CAN message, capture and display an
* error core in case of failure.
*/
if (int const rc = CAN.write(msg); rc < 0)
{
Serial.print ("CAN.write(...) failed with error code ");
Serial.println(rc);
for (;;) { }
}

/* Increase the message counter. */
msg_cnt++;

/* Only send one message per second. */
delay(1000);
}

Código de leitura CAN

/*
CANRead

Receive and read CAN Bus messages

See the full documentation here:
https://docs.arduino.cc/tutorials/uno-r4-wifi/can
*/

/**************************************************************************************
* INCLUDE
**************************************************************************************/

#include <Arduino_CAN.h>

/**************************************************************************************
* SETUP/LOOP
**************************************************************************************/

void setup()
{
Serial.begin(115200);
while (!Serial) { }

if (!CAN.begin(CanBitRate::BR_250k))
{
Serial.println("CAN.begin(...) failed.");
for (;;) {}
}
}

void loop()
{
if (CAN.available())
{
CanMsg const msg = CAN.read();
Serial.println(msg);
}
}

Quando eu preciso conectar o resistor terminal?

    1. Comunicação de longa distância: Se o barramento CAN for longo (por exemplo, mais de 1 metro), resistores terminais devem ser conectados em ambas as extremidades do barramento para evitar problemas de comunicação causados por reflexão de sinal.
    1. Comunicação com múltiplos nós: Se vários nós estiverem conectados ao mesmo barramento CAN, os resistores terminais também são indispensáveis. Eles garantem a estabilidade de impedância do barramento, evitando assim a distorção do sinal.

Quando o resistor terminal pode ser desconectado?

    1. Comunicação de curta distância: Em algumas aplicações de curta distância (normalmente menos de 1 metro), os resistores terminais podem ser omitidos, pois o impacto da reflexão de sinal na comunicação é relativamente pequeno.
    1. Comunicação com nó único: Se houver apenas um nó no barramento (como em um ambiente de depuração) e a distância for curta, o resistor terminal pode ser temporariamente desconectado.
Resultado do código do remetenteResultado do código do receptor

Suporte técnico e discussão de produtos

Obrigado por escolher nossos produtos! Estamos aqui para oferecer diferentes tipos de suporte para garantir que sua experiência com nossos produtos seja a mais tranquila possível. Oferecemos vários canais de comunicação para atender a diferentes preferências e necessidades.

Loading Comments...