Desenhe qualquer coisa em seu osciloscópio
Componentes e suprimentos
![]() |
| × | 50 | |||
![]() |
| × | 1 |
Aplicativos e serviços online
![]() |
|
Sobre este projeto
O R-2R DAC
Uma das implementações mais simples de um conversor digital para analógico pode ser alcançada projetando um DAC de escada R-2R. Este tipo de DAC só precisa de resistores para funcionar, o que o torna um DAC muito amigável para iniciantes.
O princípio básico desse tipo de DAC é que você só precisa de dois valores para os resistores. R e 2R. Em seguida, você pode configurá-los conforme mostrado no esquema abaixo.

R pode ser qualquer coisa, desde que cada ocorrência de R no esquema tenha o mesmo valor.
Por exemplo, se escolhermos R =1k, então 2R seria apenas duas vezes o valor. Neste caso, 2R =2k. Portanto, você pode usar apenas resistores de 1k e 2k.
Se você usou R =3,3K, então 2R =6,6k e assim por diante. Se você quiser apenas usar o mesmo valor de resistores para tudo, para obter 2R, você só precisa colocar os dois resistores em série e isso aumentaria sua contagem de componentes.
O número de bits é determinado por quantos ramos de 2R você tem para fora. Neste projeto, usaremos um R-2R de 8 bits e um R-2R de 6 bits para o Arduino Uno ou Nano. Se você estiver usando outro microcontrolador que sabe que suporta uma manipulação de porta completa de pelo menos 8 bits, como o STM32 "comprimido azul" e "comprimido preto", então você pode usar apenas dois DACs de 8 bits.
Observação lateral sobre ICs DAC:
Este projeto está focado no uso de um R-2R DAC, mas você pode ficar à vontade para usar um DAC IC para conseguir algo semelhante. Se você for usar um DAC IC, recomendo usar um que ofereça suporte a um protocolo de comunicação rápido, como o SPI, uma vez que I2C será muito lento para desenhar uma imagem detalhada. Não vou cobrir como usar um DAC IC neste post, mas talvez em um futuro. O R-2R ainda é meu método preferido, pois pode gerar imagens com mais detalhes.
Manipulação de porta
Estaremos usando a manipulação de porta paralela de nosso microcontrolador. A razão para fazer isso é porque permite uma velocidade de saída mais rápida e também mantém o código simples. Você pode ler mais detalhes sobre os registros de porta do Arduino neste link.
O Arduino Uno e o Nano possuem o microcontrolador ATmega328p. Este microcontrolador compartilha o mesmo mapeamento de pinos com o Atmega168:

Os pinos e bits da porta são indicados por seu rótulo PXN, onde X é a letra da porta e N é o número do bit.
Exemplo:PB1 é para a PORTA B bit 1. Da mesma forma, PC5 é para a PORTA C bit 5.
Se inspecionarmos os pinos, veremos que o microcontrolador tem portas B, C e D. Voltando à referência do Arduino, podemos ver quais portas podem ser escritas ou lidas ou ambas. Em nosso aplicativo, nos preocupamos apenas com a escrita.

A documentação afirma que o PORTD é de leitura / gravação e é mapeado para os pinos digitais de 0 a 7. Isso nos dá 8 bits completos das portas para gravação.
Em seguida, temos o PORTB que, conforme declarado, está mapeado para os pinos digitais 8-13. Uma declaração adicional é feita dizendo que 6 e 7 que completariam os 8 bits completos não estão acessíveis. Essa porta só pode ser usada para gravar 6 bits.
O mesmo é verdade para PORTC. Ele é mapeado para os pinos analógicos de 0 a 5, mas dois pinos também estão reservados, dando-nos apenas 6 bits para escrever.
Por causa dessas restrições, teremos que usar uma combinação de um DAC de 8 bits para PORTD e um DAC de 6 bits para PORTC ou PORTB.
Estaremos usando PORTD e PORTB e agora podemos começar a conectar os DACs aos pinos.
Se você precisar de algum auxílio visual sobre como montar, foi assim que montei os dois R-2Rs na placa de ensaio. Observe que usei dois R-2Rs desde que os estava testando em minha "pílula preta" STM32. Eu coloquei dois fios de ligação para fora para que eu pudesse conectar minhas pontas de prova do osciloscópio a ele e também um fio de aterramento na lateral. Usei todos os resistores de 10k, então para o meu 2R coloquei dois resistores de 10k em série.

Aqui está uma configuração de breadboard mais limpa usando o Tinkercad. Marquei as saídas com X e Y, pois essas serão as quais nossas pontas de prova do osciloscópio serão conectadas. Se você precisar de mais orientações sobre a configuração, fornecerei esquemas mostrando as escadas R-2R compostas por todos com os mesmos valores de resistor e outro com dois valores.

Certifique-se de verificar seus motivos! Toda vez que monto essa configuração, tendo a esquecer. Verifique também se você não deixou lacunas sem conexões.
ArduinoCode
Agora é a hora do esboço do Arduino.
Primeiro, precisamos configurar nossas portas para serem saídas. Da referência do Arduino sobre manipulação de portas. Podemos ver como definir as portas:

Basicamente, um valor de 1 para o bit o definirá como saída e um valor de 0 o definirá como entrada. Para PORTD, podemos escrever diretamente, uma vez que todos os bits são acessíveis. Para PORTB, lembre-se de que os bits 6 e 7 não são utilizáveis, pois são mapeados para o cristal. É uma boa prática usar bit a bit OR com valor 0 para evitar a modificação de bits que não serão definidos.
Em nosso loop de configuração, este será o código:

O código será anexado para download, portanto, não se preocupe em digitá-lo manualmente.
O loop for abaixo das configurações simplesmente remapeia os valores para a porta de 6 bits. Esses valores virão de uma lista que terá valores na faixa de 8 bits. Para remapear para 6 bits, nosso valor máximo será 2 ^ 6-1, que é 63. Estamos mapeando de um intervalo de 0 a 2 ^ 8-1, que é 255. A razão de remapearmos no código do Arduino é porque nosso a ferramenta de plotter manual produzirá os pontos xey em termos de 8 bits. Podemos alterá-lo em qualquer um dos códigos, mas é melhor alterá-lo no microcontrolador usado.
Basicamente, precisamos de algum atraso dependendo do osciloscópio. Descobri que para o meu 1 está bom. Na verdade, omitir completamente o atraso também está certo. Para pontos, ele será gerado automaticamente por nossa ferramenta de plotter manual, então você pode simplesmente copiar e colar o número, mas basicamente isso é quantos pontos existem para plotar para que a variável iterativa possa passar por eles. De qualquer forma, aqui está o código completo:

Os arrays x_points e y_points serão diferentes para você cada vez que você desenhar algo e serão gerados automaticamente com nossa ferramenta.
Observação lateral sobre PWM rápido:
Se você é um usuário avançado de microcontroladores, pode perceber que se estiver preocupado com a velocidade, então talvez o mesmo possa ser alcançado por PWM rápido e modificando registradores de clock. Em seguida, alimentar as saídas PWM em um filtro passa-baixa para obter uma tensão analógica que reduziria a contagem de pinos. Eu tentei os dois métodos e isso ainda resulta em um melhor suporte para imagens com mais detalhes. Pelo menos no Arduino Uno
Ferramenta de Desenho
Fiz essa ferramenta em Python 3 usando tkinter. Se você não tem o tkinter instalado, instale-o com pip.
pip install tk
O código será apenas anexado, mas basicamente ele registra a coordenada na janela onde o cursor foi clicado. Não tente redimensionar a janela, pois isso mudará a resolução. Se você quiser ser mais preciso, use a ferramenta de lupa do Windows. A janela é baseada em 255x255, pois esses serão os valores máximos de nossos intervalos de bits. É claro que uma das dimensões será mapeada para 6 bits se você estiver usando um Arduino UNO.
Para chamar a ferramenta basta usar este formato
python drawlog.py> arduino_list.txt
Isso criará um arquivo.txt denominado arduino_list.txt com a lista do Arduino para x_points, y_points e NUM_POINTS gerados para você, pronto para copiar e colar em seu código.
Por exemplo, é assim que o arquivo.txt fica quando você o abre. Você só precisa substituir essas linhas no código.

Aqui fica como fica depois de aberto. De lá, você pode desenhar qualquer coisa.

Desenhei a seguinte imagem para testá-la. O código é gerado ao fechar a janela.

E depois de fazer o upload do código no Arduino, era assim que parecia no modo X-Y.

IMPORTANTE:
Se ocorrer um erro de compilação falando sobre memória, isso se deve à pouca memória disponível no Arduino UNO. Isso significa que você deve desenhar uma imagem menos detalhada. Acho que a quantidade máxima de pontos foi cerca de 400, mas pode ser mais. Se você usar um STM32 "pílula azul" ou "pílula preta", esse número é para mais de 4.000.
Modo do osciloscópio X-Y
O osciloscópio deve ser definido para o modo x-y. A saída R-2R DAC de 8 bits (PORTD) será conectada ao canal 1 e a saída R-2R DAC de 6 bits (PORTB) será conectada ao canal 2. A partir daí, você pode ajustá-la com os botões giratórios até ver uma imagem.
É isso! Se você tiver alguma dúvida não hesite em perguntar. Além disso, se você quiser experimentar em uma pílula azul ou preta, aqui está o link para minha página do GitHub com um código de amostra
Agora, aqui estão algumas imagens que plotei.




Sinta-se à vontade para compartilhar o seu !!!
Editar:
Detalhes importantes para gerenciamento de memória
Como Tim mencionou nos comentários
- Em seu código Arduino, seu iterador sobre os pontos, t, é do tipo "byte", portanto, suporta apenas até 255 pontos. Por que não torná-lo um "int"?
- O código da plotadora produz "const unsigned long" para x_points e y_points - isso não funcionará porque você modificará os y-points posteriormente. Além disso, por que não usar "byte" para economizar memória?
Esteja ciente das limitações de hardware que você está usando. Para o Arduino Uno é melhor usar byte, entretanto, se você estiver usando um STM32 ou mesmo ESP32, terá mais pontos disponíveis para plotar. Obrigado a todos por seus comentários.
Timster :
Eu descobri uma maneira de aumentar enormemente o número de pontos suportados em um UNO - movê-los para o espaço de armazenamento do programa. Você pode fazer isso com o
PROGMEM
modificador. Dessa forma, você pode armazenar cerca de 15.000 pontos! Portanto, declare as matrizes assim:
const int NUM_POINTS =...
const byte x_points [NUM_POINTS] PROGMEM ={...
const byte y_points [NUM_POINTS] PROGMEM ={...
Não faça a modificação nos y_points na função de configuração (ou seja, remova o
para
loop lá). Em vez disso, faça uma pequena mudança na função de loop. Você também precisa de um comando especial para ler dados da memória do programa (pgm_read_byte_near). Portanto, o loop for no
void loop ()
parece: for (int t =0; t {
PORTD =pgm_read_byte_near (x_points + t);
PORTB =pgm_read_byte_near ( y_points + t)>> 2;
atrasoMicrosegundos (FIGURE_DELAY);
}
Então, é possível armazenar uma imagem de alta resolução ou várias imagens menores e alternar entre elas 😃
Código
- código Arduino
- Ferramenta de plotagem
Código do Arduino Arduino
Esboço do Arduino para usar em uma placa Arduino Uno ou Nanoconst byte FIGURE_DELAY =1; // traçar o atraso nos EUA. ajustar se necessárioconst int NUM_POINTS =87; // número de pontos XY na figura // coordenadas xey para plotar o byte x_points [NUM_POINTS] ={106,106,105,104,103,102,101,100,99,98,97,96,94,93,92,91 , 90,90,89,88,87,87,87,86,86,86,86,87,89,90,91,93,95,97,99,101,102,102,104,104,105,105,106,106,106,106,106,106,108,109,110,112,113,115,117,119,121,122,123,123,124,124,124,124,124,123,122,121,120,119,118,117,116,115,114,113,112,111,110,110,109,109,109,108,107,107}; y_points byte [NUM_POINTS] ={78,80 , 81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,98,99,100,101,103,105,106,108,110,112,113,113,114,115,115,115,115,115,115,114,112,112,110,109,107,106,106,108,110,112,114,114,115,116,116,117,117,117,117,117,116,115,113,112,110,108,106,104,103,102,100,99,98,97,96,95,94,93 , 92,91,90,89,87,86,84,82,81,80,78}; void setup () {// inicializar a porta D e B para escrever DDRD =B11111111; DDRB =B00111111; byte t; para (t =0; tFerramenta de plotagem Python
Ferramenta de desenho para exportar pontos para plotarimportar tkinter como tkX =[] Y =[] lastx, lasty =0, 0 # xy e addLine são apenas para fins gráficos # on_move_press é aquele que registra aquele na lista e corrige Ydef xy (evento):# registra as coordenadas quando o mouse é clicado global lastx, lasty lastx, lasty =event.x, event.ydef addLine (event):# desenha a linha do ponto antigo para o novo ponto global lastx, lasty canvas.create_line ((lastx, lasty, event.x, event.y)) # isso torna o novo ponto de partida do desenho lastx, lasty =event.x, event.y # logs clicked coordinate on listdef on_move_press (event):curX, curY =(event.x, event.y) curY =255-curY # uma vez que tkinter usa diferentes coordenadas X.append (str (curX)) Y.append (str (curY)) # configuração necessária para windowroot =tk.Tk ( ) root.geometry ("255x255") root.columnconfigure (0, weight =1) root.rowconfigure (0, weight =1) canvas =tk.Canvas (root) canvas.grid (column =0, row =0, sticky =(tk.N, tk.W, tk.E, tk.S)) # vincular clique com o botão esquerdo e arraste para as funções e inicie loopcanvas.bind ("", xy) canvas.bind (" ", addLine) root.bind (" ", on_move_press) root.mainloop () # delete cada 2ª entrada para reduzir pontos e aumentar a atualização do traço para i no intervalo (1, int (len (X) / 2)):X.pop (i) Y.pop (i) print ("const int NUM_POINTS =% s;"% str (len (X) )) print ("const unsigned long x_points [NUM_POINTS] ={% s};"% ','. join (X)) print ("const unsigned long y_points [NUM_POINTS] ={% s};"% ',' .join (Y)) # call python drawlog.py> arduino_list.txt
Esquemas




Processo de manufatura
- Resistores
- Construindo uma rede de sensores sem fio em sua casa
- Monitore a temperatura de sua casa usando o Raspberry Pi
- Os melhores acessórios para o seu Raspberry Pi
- Faça seu próprio Google Voice HAT
- Meça seu tempo de reação
- Seu guia para resistores dinâmicos
- Guia de seleção de sua serra de fita
- Como consertar a maçaneta da porta do seu carro
- Como reparar a ferrugem no seu carro?