Trilha de aprendizado · Nível 11 · Tutorial 8

Aquisição por SPI com o MCP3008

Ao concluir, o aluno será capaz de adquirir uma tensão por um MCP3008 próprio conectado ao Uno R3, configurando o SPI e interpretando o resultado conforme o protocolo do conversor.

  • Nível: Intermediário
  • Duração: 25 min
  • 8 passos
Aquisição por SPI com o MCP3008

O que você vai percorrer

  1. Reconhecer os sinais e a seleção no SPI Identifique como o Uno e o MCP3008 usam SCK, MOSI, MISO e CS para realizar uma transação SPI. 2 min
  2. Montar o MCP3008 com alimentação e referência compatíveis Monte e confira o MCP3008 alimentado em 5 V, com referência comum, desacoplamento local e uma entrada conhecida em CH0. 5 min
  3. Escolher modo, ordem dos bits e clock 3 min
  4. Formar o comando e recuperar os dez bits Codifique a solicitação de um canal simples e reconstrua o resultado de 10 bits a partir dos bytes SPI recebidos. 4 min
  5. Implementar a transação no Uno Implemente localmente uma transação SPI completa, controlando CS, lendo CH0 e exibindo o código e a tensão estimada no Monitor Serial. 4 min
  6. Comparar a aquisição com uma tensão conhecida Confronte a leitura SPI de CH0 com a tensão conhecida do divisor, usando a referência efetivamente medida. 4 min
  7. Separar transferência concluída de leitura válida Uma transferência SPI concluída não confirma, sozinha, a presença do MCP3008 nem a validade do código interpretado. 2 min
  8. Aplicação final: adquirir e validar outro canal Aplique a leitura SPI em CH1 e valide-a comparando o código com a tensão conhecida do divisor. 3 min

O que você vai aprender

  • Conectar um MCP3008 ao Uno R3 com alimentação, referência e níveis lógicos compatíveis.
  • Selecionar modo, ordem dos bits e clock a partir da folha de dados.
  • Formar o comando de aquisição e extrair o código recebido.
  • Comparar o resultado com uma tensão conhecida de um divisor resistivo.
  • Explicar por que uma transferência SPI concluída não garante que a leitura seja válida.

Antes de começar

  • Leitura de tensão com o ADC do Arduino Uno
  • Taxa de amostragem e prevenção de aliasing
  • Máscaras e operações de bits em C/C++
  • Compatibilidade elétrica entre circuitos digitais
  • Uso de folhas de dados

Passo 1 de 8

Reconhecer os sinais e a seleção no SPI

Identifique como o Uno e o MCP3008 usam SCK, MOSI, MISO e CS para realizar uma transação SPI.

O barramento da prática

SPI: clock e seleção

No SPI, o Uno atua como controlador: ele inicia a troca e fornece os pulsos de clock. O MCP3008 é um periférico: recebe os comandos e devolve dados quando está selecionado.

A comunicação é síncrona porque os bits avançam em relação ao clock compartilhado. Diferentemente do I2C, o periférico não é escolhido por um endereço dentro da mensagem: cada periférico possui sua própria linha de seleção, chamada CS.

Fluxo dos sinais

Diagrama do Uno como controlador e do MCP3008 como periférico, com SCK e MOSI indo ao conversor, MISO retornando ao Uno e CS selecionando o conversor.

O controlador fornece SCK e escolhe o periférico por CS; os dados percorrem MOSI/DIN e MISO/DOUT.

Quatro sinais, duas direções

Função de cada linha

Os quatro sinais têm papéis diferentes:

  • SCK: clock gerado pelo Uno; organiza os instantes da troca de bits.
  • MOSI (Master Out, Slave In): dados que saem do Uno e entram no MCP3008 pela entrada DIN.
  • MISO (Master In, Slave Out): dados que saem do MCP3008 pela saída DOUT e entram no Uno.
  • CS (Chip Select): seleção individual do MCP3008.

Enquanto CS estiver em nível alto, o MCP3008 fica desmarcado. A transação acontece com CS em nível baixo: o Uno o leva a baixo antes da sequência de clock e o devolve a alto ao terminar.

Dica

Troca simultânea

Cada pulso de SCK movimenta bits nos dois sentidos: o Uno pode enviar um bit por MOSI ao mesmo tempo que recebe um bit por MISO. Isso é normal mesmo quando, em uma parte da transação, apenas um sentido contém informação útil para a aplicação.

CS evita conflito no retorno

Quando há mais de um periférico

Imagine um barramento com dois periféricos. SCK, MOSI e MISO podem ser compartilhados, mas cada periférico precisa de um CS próprio.

O controlador só deve deixar um periférico que possa responder por MISO selecionado por vez. Os outros permanecem desmarcados e liberam MISO, isto é, não tentam impor nível alto ou baixo nessa linha. Assim, o periférico selecionado é o único a devolver dados.

Um periférico e um barramento compartilhado

Comparação entre a ligação de um único MCP3008 e um barramento SPI com dois periféricos, CS individuais e MISO compartilhado.

Na prática inicial há um MCP3008. Em um barramento compartilhado, CS decide qual periférico pode usar MISO.

Verifique seu entendimento

Revise os sinais

Associe cada sinal SPI à sua função principal.

Decida sobre a seleção

Em um barramento SPI com dois periféricos, é seguro deixar os dois CS em nível baixo se ambos puderem dirigir MISO.

Passo 2 de 8

Montar o MCP3008 com alimentação e referência compatíveis

Monte e confira o MCP3008 alimentado em 5 V, com referência comum, desacoplamento local e uma entrada conhecida em CH0.

Prepare os componentes e identifique o CI

Prepare a montagem

Separe: Uno R3 e cabo USB, MCP3008 DIP-16, protoboard, jumpers, multímetro, dois resistores de 1 kΩ, um resistor de 10 kΩ e dois capacitores cerâmicos de 100 nF.

Faça toda conexão ou alteração com o USB desconectado. O MCP3008 será alimentado pelo Uno em 5 V; portanto, os sinais SPI de 5 V são compatíveis nesta montagem.

Oriente o encapsulamento

Vista superior de um MCP3008 DIP-16, com a marca de orientação no topo e a numeração dos pinos em sentido anti-horário.

Com a marca do encapsulamento voltada para cima, o pino 1 fica no canto superior esquerdo. CH0 é o pino 1; os canais seguem até CH7 no pino 8.

Faça o cabeamento digital e da alimentação

Conecte alimentação e SPI

Posicione o MCP3008 atravessando o vão central da protoboard. Use a tabela para fazer as conexões principais. VDD e VREF usam o trilho de 5 V do Uno; AGND e DGND usam o mesmo GND do Uno. Não conecte VREF ao pino AREF do Arduino.

Os capacitores de 100 nF devem ficar fisicamente próximos ao MCP3008: um entre VDD e GND e outro entre VREF e GND.

Mapa de conexões

Conexões do MCP3008 ao Uno R3 e aos trilhos da protoboard.

Confira o número do pino diretamente no encapsulamento orientado.
MCP3008PinoConectar a
CH01Ponto médio do divisor
DGND9GND comum
CS/SHDN10D10 e resistor de 10 kΩ ao 5 V
DIN11D11 / MOSI
DOUT12D12 / MISO
CLK13D13 / SCK
AGND14GND comum
VREF155 V
VDD165 V

Veja o conjunto das conexões

Diagrama de ligação entre o Uno, o MCP3008, os trilhos de 5 V e GND e os dois capacitores de desacoplamento.

SCK, MOSI e MISO chegam ao conversor; CS é individual. Os dois terras e as duas alimentações devem estar conectados aos trilhos corretos.

Dica

Mantenha CS em estado seguro

O resistor de 10 kΩ liga CS/SHDN ao 5 V. Ele mantém o MCP3008 desmarcado enquanto o Uno reinicia. No sketch do próximo step, D10 também será configurado como saída, preservando o Uno como controlador SPI.

Monte a entrada e confira as tensões

Crie a entrada conhecida

Monte o divisor que fornecerá uma tensão conhecida:

5 V → resistor de 1 kΩ → nó de medição → resistor de 1 kΩ → GND

Ligue o nó de medição a CH0 (pino 1). Com resistores iguais, a previsão é aproximadamente VREF/2. Como os resistores estão em paralelo vistos pela entrada, a resistência de Thévenin da fonte é 500 Ω, adequada para esta prática.

Não aplique tensão externa, tensão negativa nem tensão acima de VREF a qualquer canal analógico.

Divisor ligado a CH0

Dois resistores de 1 kΩ em série entre 5 V e GND, com o ponto médio conectado a CH0 do MCP3008.

O ponto médio é a tensão que será comparada depois com a leitura digital do MCP3008.

Atenção

Energize e meça com cuidado

Antes de conectar o USB, confira a orientação do CI, a continuidade dos terras e a ausência de curto entre 5 V e GND. Só então energize.

Com o multímetro em tensão contínua, use o GND comum como ponta de referência e anote as três medições abaixo. Valores reais podem diferir um pouco dos valores nominais.

Anote suas medições

Registro local antes da aquisição.

Preencha no caderno ou em uma anotação local.
GrandezaPrevisão nominalMedição
VDD em relação ao GNDPróxima de 5 VAnote
VREF em relação ao GNDPróxima de 5 VAnote
CH0 em relação ao GNDPróxima de VREF/2Anote

Valide a montagem antes de programar

Confira as conexões críticas

Associe cada conexão à sua função na montagem.

Toque em um item e depois no par correspondente.

Registre a conferência

Com a montagem energizada e conferida, registre suas medidas de VDD, VREF e CH0. Compare CH0 com aproximadamente metade de VREF e descreva qualquer diferença pequena que tenha observado.

Escreva pelo menos 40 caracteres (0/40).

Passo 3 de 8

Escolher modo, ordem dos bits e clock

Interpretar a temporização do MCP3008

Temporização escolhida: modo 0

Clock: repouso, transições e amostragem

No SPI, CPOL define o nível de repouso de SCK: baixo quando CPOL = 0 e alto quando CPOL = 1. CPHA define em qual borda o receptor captura o dado, em relação às transições do clock.

Para o MCP3008, a entrada DIN é capturada na subida de CLK. A saída DOUT é atualizada na descida, para que o controlador possa ler um bit estável na subida seguinte.

Assim, uma escolha prática compatível é SPI_MODE0: clock em repouso baixo e captura na primeira borda, que é a borda de subida. O dispositivo também aceita o modo 3, mas neste tutorial será usado o modo 0.

Leitura e atualização nos pulsos de clock

Diagrama de temporização com clock em repouso baixo, dados DIN estáveis na subida e dados DOUT mudando na descida.

No modo 0, o controlador apresenta DIN antes da subida; o MCP3008 atualiza DOUT na descida para o próximo instante de leitura.

Justificar ordem, frequência e fonte

Parâmetros da configuração

Os parâmetros abaixo vêm das condições documentadas para o MCP3008 alimentado a 5 V nesta prática. Eles devem ser escolhidos em conjunto: uma configuração de clock incompatível pode deslocar ou corromper os bits, mesmo com os fios conectados corretamente.

Decisões para esta prática

Configuração adotada para a montagem com Uno R3 e MCP3008 a 5 V.

A frequência escolhida é deliberadamente menor que o máximo documentado.
ParâmetroDado do MCP3008Escolha prática
Modos SPIModos 0 ou 3SPI_MODE0
Ordem dos bitsMais significativo primeiroMSBFIRST
Clock máximo a 5 V3,6 MHz1 MHz
Repouso de SCK no modo 0Nível baixoBaixo
Captura de DINBorda de subidaPrimeira borda

Exemplo

Clock e fonte analógica

1 MHz é uma escolha conservadora, não um limite universal do componente. O limite de 3,6 MHz depende das condições especificadas na folha de dados, incluindo a alimentação de 5 V.

O MCP3008 dispõe de uma janela de aquisição de aproximadamente 1,5 período de clock. Com SCK de 1 MHz, um período dura 1 µs; portanto, essa janela é de cerca de 1,5 µs. O divisor já montado tem resistência de Thévenin de 500 Ω, uma fonte de baixa impedância adequada a essa escolha. Isso não torna qualquer fonte adequada: fontes mais resistivas podem exigir análise ou condicionamento.

Separar clock de cadência

Clock não é taxa de amostragem

Não confunda três grandezas:

  • Frequência de SCK: pulsos por segundo na linha de clock.
  • Duração da transação: tempo em que a seleção fica ativa e os bits da leitura são transferidos.
  • Intervalo entre aquisições: decisão do firmware sobre quando iniciar a próxima conversão.

Por exemplo, SCK de 1 MHz fornece períodos de 1 µs, mas o programa pode iniciar uma aquisição a cada 100 ms. Nesse caso, a cadência é aproximadamente 10 aquisições por segundo, e não um milhão.

Verifique sua escolha

Para a montagem a 5 V, qual configuração e interpretação estão corretas?

Passo 4 de 8

Formar o comando e recuperar os dez bits

Codifique a solicitação de um canal simples e reconstrua o resultado de 10 bits a partir dos bytes SPI recebidos.

Identifique os campos de seleção

Campos da solicitação

Para pedir uma conversão, o Uno envia ao MCP3008 um comando com quatro campos: bit de início, seleção SGL/DIFF e três bits de canal.

Nesta prática, use apenas entrada simples (single-ended): cada canal é medido em relação a AGND. Nesse formato, o campo SGL/DIFF vale 1. Os três bits seguintes selecionam CH0 a CH7:

  • CH0 = 000
  • CH1 = 001
  • …
  • CH7 = 111

O comando será dividido em bytes porque SPI.transfer() troca oito bits por vez. Isso não muda o protocolo: apenas organiza seus bits para a transferência SPI.

Estrutura do comando

Diagrama que separa o bit de início, a seleção de entrada simples e os três bits de canal no comando SPI.

Os campos úteis ocupam parte dos dois primeiros bytes; os demais bits apenas completam o enquadramento.

Enquadre a solicitação em bytes

Três bytes, uma transação

Para um canal armazenado na variável canal (de 0 a 7), envie estes três bytes enquanto CS estiver em nível baixo:

  1. 0x01 — coloca o bit de início na posição esperada.
  2. 0x80 | (canal << 4) — coloca SGL/DIFF = 1 e os três bits do canal.
  3. 0x00 — envia bits neutros e, principalmente, fornece clocks para o MCP3008 terminar de deslocar o resultado.

Para CH0, o segundo byte é 0x80; para CH1, é 0x90; para CH7, é 0xF0. O 0x80 já representa o bit de entrada simples.

Exemplo

Exemplo para CH3

Exemplo: selecionar CH3 em entrada simples

  • canal = 3, ou 011 em binário.
  • canal << 4 resulta em 0011 0000 (0x30).
  • 0x80 | 0x30 resulta em 1011 0000 (0xB0).

Assim, os bytes transmitidos são: 0x01, 0xB0, 0x00.

CS deve ficar baixo desde antes do primeiro byte até depois do terceiro. Levantar CS no meio da sequência encerraria a transação antes de todos os bits necessários serem transferidos.

Reconstrua o resultado de 10 bits

Separe os bits de conversão

SPI recebe um byte ao mesmo tempo que transmite outro. Chame os bytes recebidos de rx0, rx1 e rx2, na mesma ordem dos três bytes enviados.

rx0 não contém resultado útil e deve ser descartado. Em rx1, os bits iniciais são de enquadramento, incluindo o bit nulo previsto pelo protocolo. Apenas seus dois bits menos significativos são dados convertidos: B9 e B8.

O byte rx2 contém B7 até B0. Portanto, o código de 10 bits é reconstruído com:

((rx1 & 0x03) << 8) | rx2

A máscara 0x03 preserva somente B9 e B8. O deslocamento de oito posições os leva à parte alta do resultado; o OR combina essa parte com os oito bits de rx2. O resultado possível vai de 0 a 1023.

De bytes recebidos a código

Diagrama de três bytes SPI mostrando rx0 descartado, dois bits úteis em rx1 e oito bits úteis em rx2.

A conversão não ocupa um byte inteiro: os dois bits altos vêm do final de rx1 e os oito restantes vêm de rx2.

Verifique a interpretação dos bytes

Pratique a montagem e a extração

Complete a formação do segundo byte transmitido e a extração do código convertido. Considere que canal já foi limitado ao intervalo de 0 a 7 e que rx1 e rx2 são os dois últimos bytes recebidos.

cpp
uint8_t tx1 = 0x80 | ( << 4);

uint16_t codigo = ((rx1 & ) << 8) | ;

Passo 5 de 8

Implementar a transação no Uno

Implemente localmente uma transação SPI completa, controlando CS, lendo CH0 e exibindo o código e a tensão estimada no Monitor Serial.

Preparar a transação

O que a biblioteca configura — e o que você controla

O sketch usará apenas SPI.h, já fornecida pelo núcleo Arduino AVR. Antes de copiar o código, substitua o valor de VREF pela tensão que você mediu entre VREF e GND na sua montagem. O valor 4.96 no exemplo não é obrigatório.

SPI.beginTransaction() aplica 1 MHz, MSBFIRST e SPI_MODE0, mas não seleciona o MCP3008. A seleção elétrica ocorre somente quando D10 vai para nível baixo. Ele deve permanecer baixo durante as três transferências e voltar a alto antes de SPI.endTransaction().

Enquadramento da aquisição

Diagrama do fluxo de uma aquisição: configurar SPI, baixar CS, transferir três bytes, elevar CS e montar um resultado de 10 bits.

CS delimita eletricamente os três bytes. Cada transfer() envia um byte e recebe outro ao mesmo tempo.

Copiar, gravar e observar

Sketch completo para CH0

Copie todo o sketch em um único arquivo na IDE Arduino. Ajuste somente VREF para a sua medição antes de compilar e gravar.

cpp
#include <SPI.h>

const byte CS_PIN = 10;
const float VREF = 4.96;  // Use a VREF medida
byte canalExibido = 0;

SPISettings mcp3008SPI(1000000, MSBFIRST, SPI_MODE0);

uint16_t lerMCP3008(byte canal) {
  if (canal > 7) return 0;
  canalExibido = canal;

  SPI.beginTransaction(mcp3008SPI);
  digitalWrite(CS_PIN, LOW);
  byte rx0 = SPI.transfer(0x01);
  byte rx1 = SPI.transfer(0x80 | (canal << 4));
  byte rx2 = SPI.transfer(0x00);
  digitalWrite(CS_PIN, HIGH);
  SPI.endTransaction();

  return ((uint16_t)(rx1 & 0x03) << 8) | rx2;
}

void setup() {
  pinMode(CS_PIN, OUTPUT);
  digitalWrite(CS_PIN, HIGH);
  Serial.begin(115200);
  SPI.begin();
}

void loop() {
  static unsigned long ultimaLeitura = 0;

  if (millis() - ultimaLeitura >= 100) {
    ultimaLeitura = millis();
    uint16_t codigo = lerMCP3008(0);
    float tensao = codigo * VREF / 1024.0;

    Serial.print("CH");
    Serial.print(canalExibido);
    Serial.print("  codigo=");
    Serial.print(codigo);
    Serial.print("  tensao=");
    Serial.print(tensao, 3);
    Serial.println(" V");
  }
}
Saída esperada
CH0  codigo=510  tensao=2.470 V
CH0  codigo=511  tensao=2.475 V
CH0  codigo=510  tensao=2.470 V

Exemplo ilustrativo: os códigos e a tensão variam conforme a VREF realmente medida, os resistores e a montagem. Após mudar a chamada para `lerMCP3008(1)`, o rótulo passa automaticamente para CH1.

Leia o sketch por blocos

rx0 é recebido porque toda transferência SPI ocorre nos dois sentidos, mas ele não contém parte útil da conversão e é descartado. Já rx1 e rx2 formam o código de 10 bits.

O controle de canalExibido faz o rótulo serial acompanhar o argumento usado em lerMCP3008(). Assim, quando você trocar futuramente lerMCP3008(0) por lerMCP3008(1), a saída mostrará CH1.

Dica

Dois encerramentos necessários

digitalWrite(CS_PIN, HIGH) encerra a seleção elétrica do MCP3008; por isso vem logo após o terceiro transfer(). SPI.endTransaction() encerra o contexto de parâmetros da biblioteca. São ações diferentes e ambas devem ocorrer em cada aquisição.

Verificar a ordem da transação

A sequência que protege o enquadramento

Com a montagem já conferida, compile e grave o sketch. Abra o Monitor Serial local em 115200 bit/s. A cada cerca de 100 ms, o Uno solicita CH0, reconstrói o código e calcula codigo × VREF / 1024.0 em ponto flutuante.

Agora organize a sequência interna da função de leitura. Considere as três chamadas de SPI.transfer() como uma única etapa: elas precisam ocorrer sem interromper a seleção do conversor.

Ordene a transação

Ordene as etapas de uma aquisição SPI do MCP3008.

  1. digitalWrite(CS_PIN, HIGH)
  2. SPI.endTransaction()
  3. Executar os três SPI.transfer()
  4. digitalWrite(CS_PIN, LOW)
  5. SPI.beginTransaction(mcp3008SPI)

Praticar o controle explícito

Fixar os limites da aquisição

Complete as chamadas que delimitam corretamente uma aquisição. Não altere a ordem: a biblioteca aplica parâmetros, mas o programa deve controlar explicitamente a seleção por CS.

Complete o controle de CS

Preencha as chamadas essenciais de seleção e encerramento.

cpp
SPI.beginTransaction(mcp3008SPI);
digitalWrite(CS_PIN, );

byte rx0 = SPI.transfer(0x01);
byte rx1 = SPI.transfer(0x80 | (canal << 4));
byte rx2 = SPI.transfer(0x00);

digitalWrite(CS_PIN, );

Passo 6 de 8

Comparar a aquisição com uma tensão conhecida

Confronte a leitura SPI de CH0 com a tensão conhecida do divisor, usando a referência efetivamente medida.

Identifique os três valores da leitura

Ler a saída

O que observar no monitor serial

Com o sketch anterior gravado e o Monitor Serial em 115200 bit/s, cada linha deve trazer três informações:

  • CH0: o canal solicitado;
  • código: resultado bruto de 0 a 1023;
  • V estimada: conversão do código usando a constante VREF medida na sua montagem.

Para o divisor de dois resistores de 1 kΩ entre 5 V e GND, o ponto médio ligado a CH0 é previsto como aproximadamente metade de VREF. Assim, o código tende a ficar perto do meio da escala: 512, mas não precisa ser exatamente esse número.

Esquema visual da comparação entre o divisor, o multímetro, o MCP3008 e os dados exibidos no monitor serial.

Compare a tensão do mesmo ponto físico: a junção dos dois resistores.

Dica

O monitor serial mostra o que o sketch calculou; ele não substitui a medição no seu circuito. Meça com o multímetro entre o ponto médio do divisor e o GND comum, sem mudar as conexões durante a comparação.

Faça a comparação quantitativa

Compare valores equivalentes

Três referências para confrontar

Use estas três referências para avaliar a leitura de CH0:

  1. Previsão do divisor: com resistores iguais, aproximadamente VREF / 2.
  2. Medição no multímetro: tensão real entre o ponto médio e GND.
  3. Estimativa do MCP3008: código × VREF / 1024.0.

Use a VREF que você mediu na montagem. Embora VDD e VREF estejam ligados ao trilho de 5 V nesta prática, “5,00 V” é um valor nominal, não uma medição.

Exemplo

Exemplo de concordância

Exemplo ilustrativo, não é um resultado obrigatório:

  • VREF medida: 4,92 V
  • Previsão do divisor: 4,92 / 2 = 2,46 V
  • Código observado: 510
  • Estimativa: 510 × 4,92 / 1024 = 2,45 V
  • Multímetro no ponto médio: 2,46 V

Os três valores estão próximos. O código 510, em vez de 512, não representa por si só um problema.

Dica

Pequenas diferenças são esperadas: tolerância dos resistores, erro e quantização do conversor, resolução do multímetro e flutuações entre conversões influenciam os números. Procure coerência com a tensão conhecida, não igualdade perfeita.

Registre algumas leituras

Registro local

Anote medições sucessivas sem alterar a montagem. Registre a VREF uma vez e preencha as linhas com o valor exibido pelo monitor e a estimativa correspondente. Se o sketch já imprime a estimativa, use-a e confira se ela é compatível com o cálculo.

Modelo para seu registro. Preencha com os valores da sua montagem.

Comparação de CH0 com o divisor resistivo
VREF medida (V)V divisor medida (V)Código CH0V estimada (V)
________________________________
________________________________
________________________________

Atenção

Meça também VREF em relação ao GND comum. Não use uma entrada analógica desconectada como referência de comparação: ela pode ficar flutuante e não representa a tensão do divisor.

Prática: interprete sua comparação

Descreva a evidência obtida

Relate sua comparação de CH0. Inclua: a VREF medida, a tensão medida no ponto médio, pelo menos dois códigos observados e uma estimativa de tensão. Diga se os valores foram coerentes com aproximadamente metade da referência e explique por que não é necessário obter exatamente o código 512.

Escreva pelo menos 120 caracteres (0/120).

Passo 7 de 8

Separar transferência concluída de leitura válida

Uma transferência SPI concluída não confirma, sozinha, a presença do MCP3008 nem a validade do código interpretado.

Transferência não é ACK

O que o retorno de transfer informa

Transferir não é confirmar

No SPI, SPI.transfer() sempre faz o Uno deslocar 8 bits enquanto gera pulsos de clock. Ao mesmo tempo, ele devolve os 8 níveis que foram lidos em MISO.

Isso não equivale a um ACK. Diferentemente do I²C, não há um bit padronizado pelo SPI que diga: “o MCP3008 recebeu e confirmou”. Portanto, três chamadas a transfer() concluídas provam apenas que o controlador executou a sequência de clock e leitura.

Elas não provam, por si só, que o MCP3008 estava conectado, selecionado por CS baixo ou respondendo conforme seu protocolo.

Clock ocorre mesmo sem confirmação

Diagrama comparando uma troca SPI com MCP3008 selecionado a uma troca em que MISO não é dirigido pelo periférico.

O Uno pode gerar clock e receber bytes em ambos os casos; somente a coerência dos dados ajuda a sustentar a interpretação.

Evidência vem da coerência

Faixa válida, conclusão inválida

Um número possível não é uma leitura comprovada

O MCP3008 produz códigos de 0 a 1023. Assim, um resultado dentro dessa faixa é necessário, mas não suficiente para considerá-lo válido.

  • 0 pode representar uma entrada próxima de GND.
  • 1023 pode representar uma entrada próxima de VREF.
  • Um valor intermediário pode ser correto — ou pode ser consequência de modo SPI, comando, CS ou bytes interpretados incorretamente.

Se o MCP3008 estiver ausente ou não selecionado, MISO pode ficar sem acionamento definido. Os bytes lidos nessa condição não têm um padrão universal confiável: não use um valor isolado como teste de presença.

Exemplo

Três interpretações prudentes

Caso A — leitura do divisor: VREF medida = 4,96 V; divisor medido = 2,47 V; vários códigos ficam perto de 510; a tensão estimada fica perto de 2,47 V. Aqui há coerência entre uma entrada conhecida, a referência e o resultado.

Caso B — código 1023: esse valor sozinho não demonstra defeito. Ele pode ser esperado se a entrada estiver muito próxima de VREF. Seria preciso confrontá-lo com a tensão realmente presente em CH0 e com a referência.

Caso C — bytes recebidos após uma transferência: sem uma entrada conhecida e sem confirmar a seleção por CS, qualquer código de 0 a 1023 ainda pode ser enganoso.

Verifique a conclusão

Conclusão sobre transfer

Verdadeiro ou falso: se as três chamadas a SPI.transfer() retornaram bytes, então o MCP3008 está certamente presente e respondeu corretamente.

Códigos nos extremos

Verdadeiro ou falso: um código 0 ou 1023, isoladamente, prova que há defeito na montagem.

Aplique o critério

Justifique uma leitura confiável

Seu divisor foi medido em 2,48 V e VREF em 4,96 V. O sketch, configurado em SPI_MODE0, mostra códigos próximos de 512 e tensão estimada próxima de 2,48 V.

Em uma ou duas frases, cite as evidências que tornam essa leitura mais confiável do que simplesmente saber que SPI.transfer() retornou bytes.

Escreva pelo menos 80 caracteres (0/80).

Passo 8 de 8

Aplicação final: adquirir e validar outro canal

Aplique a leitura SPI em CH1 e valide-a comparando o código com a tensão conhecida do divisor.

Transferir o divisor para CH1

Transfira o divisor para CH1

Aplicação final: mova a entrada conhecida para CH1

Use o mesmo divisor de 1 kΩ + 1 kΩ, mas transfira seu ponto médio de CH0, pino 1, para CH1, pino 2, do MCP3008.

  1. Desconecte o USB do Uno.
  2. Remova somente o jumper entre o ponto médio do divisor e CH0.
  3. Conecte esse ponto médio a CH1 (pino 2).
  4. Mantenha todas as demais ligações, inclusive VDD, VREF, AGND, DGND, DIN, DOUT, CLK, CS e os capacitores.
  5. Confira a posição do pino 2 antes de energizar novamente.

CH0 pode permanecer sem conexão, mas não o use como referência de comparação: uma entrada flutuante não representa uma tensão conhecida e pode produzir leituras variáveis.

A nova ligação do divisor

Diagrama de um divisor de dois resistores iguais cujo ponto médio está ligado à segunda entrada analógica do MCP3008; a primeira entrada está sem conexão.

A única mudança física é levar o ponto médio do divisor ao CH1, pino 2, com a alimentação desligada.

Dica

Preveja antes de energizar

Como os resistores, a alimentação e a referência não mudaram, a previsão também não muda: o ponto médio deve continuar próximo de VREF/2. Portanto, o código deve tender à metade da escala, perto de 512, sem obrigação de ser exatamente 512.

Ajustar o sketch sem alterar o protocolo

Mantenha canal e rótulo coerentes

No sketch anterior, use uma constante única para indicar o canal da prática. Ela será usada tanto na chamada de leitura quanto no rótulo enviado ao Monitor Serial. Assim, a saída não poderá identificar CH1 como se fosse CH0.

Faça as substituições mostradas abaixo: a constante fica junto das demais declarações globais; dentro de lerMCP3008(), remova a linha canalExibido = canal;; e, no loop(), use CANAL_MEDIDO nas duas posições indicadas.

Ajuste do sketch para CH1

Substitua byte canalExibido = 0; por esta constante, remova a atribuição a canalExibido da função e ajuste as duas linhas do loop(). Mantenha SPI_MODE0, 1 MHz, MSBFIRST, CS, VREF e a extração dos 10 bits sem alterações.

cpp
const byte CANAL_MEDIDO = 1;

uint16_t lerMCP3008(byte canal) {
  if (canal > 7) return 0;

  SPI.beginTransaction(mcp3008SPI);
  digitalWrite(CS_PIN, LOW);
  byte rx0 = SPI.transfer(0x01);
  byte rx1 = SPI.transfer(0x80 | (canal << 4));
  byte rx2 = SPI.transfer(0x00);
  digitalWrite(CS_PIN, HIGH);
  SPI.endTransaction();

  return ((uint16_t)(rx1 & 0x03) << 8) | rx2;
}

// Dentro do bloco temporizado em loop():
uint16_t codigo = lerMCP3008(CANAL_MEDIDO);
float tensao = codigo * VREF / 1024.0;

Serial.print("CH");
Serial.print(CANAL_MEDIDO);
Saída esperada
CH1  codigo=511  tensao=2.475 V
CH1  codigo=510  tensao=2.470 V
CH1  codigo=511  tensao=2.475 V

Os valores numéricos variam conforme VREF, resistores e medições reais. O ponto essencial é o rótulo CH1 e a tensão próxima da metade da referência.

Complete a seleção de CH1

Complete a constante que seleciona o canal onde o divisor foi conectado. A mesma constante deve continuar sendo usada na chamada lerMCP3008(CANAL_MEDIDO) e na impressão do rótulo serial.

Canal compartilhado

Preencha o número do canal conectado ao divisor.

cpp
const byte CANAL_MEDIDO = ;

Validar CH1 com uma tensão conhecida

Compare a leitura de CH1

Depois da conferência visual, reconecte o USB e abra o Monitor Serial em 115200 bit/s. Observe algumas linhas identificadas como CH1 e compare três referências da mesma tensão:

  • Previsão do divisor: aproximadamente VREF / 2.
  • Multímetro: tensão entre o ponto médio do divisor e o GND comum.
  • MCP3008: valor calculado pelo sketch, código × VREF / 1024.0.

Mover o mesmo ponto médio de CH0 para CH1 não deve alterar substancialmente a tensão observada. Diferenças pequenas entre código, estimativa e multímetro são compatíveis com tolerância dos resistores, quantização, erro dos instrumentos e flutuações normais.

Três evidências para a mesma tensão

Comparação entre um divisor de resistores iguais, a medição do ponto médio por multímetro e uma saída serial identificada como canal 1 perto da metade da escala.

A leitura é mais sustentada quando previsão, medição direta e estimativa do código concordam aproximadamente.

Relate sua comparação

Registre a evidência da sua montagem. Informe VREF, a tensão medida no ponto médio, pelo menos um código de CH1 e a tensão estimada. Depois, diga se a comparação foi coerente com aproximadamente metade de VREF.

Escreva pelo menos 80 caracteres (0/80).

Revisão e encerramento

Comunicação executada não basta

Uma cadeia SPI concluída só mostra que o Uno gerou clocks e leu níveis em MISO durante as transferências. Ela não fornece um ACK padronizado que comprove presença do MCP3008 ou validade da conversão.

Nesta aplicação, a leitura de CH1 ganha evidência porque reúne: conexão e alimentação compatíveis, parâmetros documentados, CS baixo durante os três bytes, comando do canal correto, extração dos dez bits e comparação com a tensão conhecida do divisor. Um código como 509, sozinho, ainda é apenas um número interpretado a partir dos bytes recebidos.

Faça a conclusão prudente

Uma leitura de CH1 retorna código 509 após as três transferências SPI. Explique qual conclusão é possível apenas com esse retorno e quais evidências da prática são necessárias para sustentar que a medição é válida.

Escreva pelo menos 110 caracteres (0/110).

Resumo

Síntese da competência

  • Transfira o ponto médio do divisor para CH1, pino 2, somente com a alimentação desligada.
  • Use uma constante de canal compartilhada pela leitura e pelo rótulo do Monitor Serial para exibir CH1 corretamente.
  • Preserve modo SPI, clock, referência, CS e a extração de dez bits; somente o canal muda.
  • Compare previsão do divisor, multímetro e tensão estimada com a VREF medida.
  • Uma transferência SPI concluída não comprova sozinha presença do conversor nem validade da medição.

Baixe o Aplicativo agora para ter acesso a + de 5000 cursos gratuitos, exercícios, certificado e muito conteúdo sem pagar nada!

  • Cursos online 100% gratuitos do início ao fim

    Milhares de cursos online em vídeo, ebooks e áudiobooks.

  • Mais de 60 mil exercícios gratuitos

    Para testar seus conhecimentos no decorrer dos cursos online

  • Certificado Digital gratuito válido em todo o Brasil

    Gerado diretamente na galeria de fotos do seu celular e enviado ao seu e-mail

Aplicativo Cursa na tela de ebook, na tela de curso em vídeo e na tela de exercícios do curso, mais o certificado de conclusão de curso