Mostrando postagens com marcador projetos. Mostrar todas as postagens
Mostrando postagens com marcador projetos. Mostrar todas as postagens

sábado, 20 de dezembro de 2014

Tricarneiro - Ep. 7 - Detector de bateria fraca

Dicas de como configurar o sensor de voltagem (bateria fraca) da controladora kk 2.1 para multirotores como o tricóptero Tricarneiro, com frame Bat Bone (Flite Test).

Veja também dicas de como carregar baterias de LiPo (lítio polímero) com segurança.



No YouTube: http://youtu.be/mZW_C9y9VYA?list=UUgP9UJRSxYe687HhHYsBwYA

Para evitar curtos na placa, você deve garantir que não conectará o positivo da bateria no negativo do sensor de bateria.

Este cara foi mais extremo e arrancou o pino GND:

http://forum.flitetest.com/showthread.php?6922-First-Bat-Bone-Build/page3

Eu só o cobri com um jumper.

Abs!
Otávio

Para ver todos os posts deste projeto, você pode clicar no marcador "tricarneiro".

domingo, 14 de dezembro de 2014

Tricarneiro, o drone - Ep. 8 - Câmeras

Último vídeo do Tricarneiro (será?)

Neste vídeo, mostro as câmeras que já utilizei nele:

- Sony Action 
- Câmera chaveiro espiã (Mercado Livre)



No YouTube: https://www.youtube.com/watch?v=UJ3ND7pyw30&list=UUgP9UJRSxYe687HhHYsBwYA

Este também é o primeiro vídeo que montei utilizando o kdenlive. Gostei muito!

Abraços,
Otávio

Para ver todos os posts deste projeto, você pode clicar no marcador "tricarneiro".

terça-feira, 4 de novembro de 2014

Tricarneiro, o drone - Ep. 6 - Primeiros Vôos

Pessoal,

Depois de muita luta, finalmente consegui fazer o Tricarneiro (meu tricóptero) voar bem! Vejam aí!


Ver direto no YouTube: http://youtu.be/S-g4FcGZLbM?list=UUgP9UJRSxYe687HhHYsBwYA

Para conseguir fazer isso, esta é a configuração que fiz na placa KK2.1:





PI Editor
Axis: Roll (Aileron)
P Gain: 35
P Limit: 100
I Gain: 25
I Limit: 20


PI Editor
Axis: Pitch (Elevator) - Profundor(?)
P Gain: 35
P Limit: 100
I Gain: 25
I Limit: 20
 

PI Editor
Axis: Yaw (Rudder) - Leme
P Gain: 15
P Limit: 80
I Gain: 20
I Limit: 20



Mode Settings
Self-Level: AUX (Channel 5)
Link Roll Pitch: Yes
Auto Disarm: Yes
CPPM Enabled: No

Stick Scaling
Roll (Ail):  30
Pitch (Ele): 30
Yaw (Rud) : 25
Throttle: 90



Misc. Settings
Minimum throttle: 10
Height Dampening: 0
Height D. Limit: 30
Alarm 1/10 volts: 105 (dispara o alarme de bateria fraca em 10,5 V)
Servo filter: 60
(antes de descobrir que meu tricóptero rodava descontrolado devido à configuração do Mixer Editor abaixo, mexi muito aqui sem nenhum sucesso)


 Self-level Settings
P Gain: 65
P limit: 65
ACC Trim Roll: 0
ACC Trim Pitch: 0


Camera Stab Settings
Roll gain: 0
Roll offset: 50
Pitch gain: 0
Pitch offset: 50



CPPM settings
Roll (Ail): 1
Pitch (Ele): 2
Throttle: 3
Yaw (Rud) : 4
AUX : 5 (lembra que o self level estava definido para AUX? É este canal 5)


Mixer Editor
CH:1
Throttle: 100
Aileron: -87
Elevator: 50
Rudder: 0
Offset: 0
Type: ESC
Rate: High


Mixer Editor
CH:2
Throttle: 100
Aileron: 87
Elevator: 50
Rudder:-1 (acho que era para ser 0, não?)
Offset: 0
Type: ESC
Rate: High


Mixer Editor
CH:3
Throttle: 100
Aileron:0
Elevator: -100
Rudder: 0
Offset: 0
Type: ESC
Rate: High


Mixer Editor (esta é a configuração importante!)
CH:4
Throttle: 0
Aileron: 0
Elevator: 0
Rudder: -100
Offset:50
Type: Servo
Rate:Low

Se o seu tricóptero fica girando descontroladamente em parafuso sempre que sai do chão, confira esta configuração.

Ao trocar o mecanismo que dá suporte ao servo (que serve de leme e faz o movimento de yaw), tive que trocar de novo o rudder para 100 (positivo) e entendi o que acontece. Na peça fornecida pela Flight Test (a que uso neste vídeo), o servo fica virado para a frente, na direção da placa KK2.1. Nesta situação, o rudder deve ficar em -100. Se seu servo fica virado para trás (usando um servo mount do Turnigy Talon, como fiz depois), o rudder deve ficar em 100 (positivo).

Acontece que se o servo está virado na direção oposta ao que é esperado pela controladora, o controle dele deve ser invertido! Parece óbvio depois que vi as duas situações, mas não fazia ideia que existiam estas duas possibilidades... Agora você sabe! 
 






Motor Layout
No meu layout, os motores 1 e 3 giram na direção horária e o motor 2 na direção anti-horária. Se você inverter o controle do rudder, a controladora pode se confundir e mostrar todos os motores girando iguais. Não se preocupe com isso.






Meu motor 4 é o servo da cauda e os demais não foram utilizados.





Espero que este post ajude alguém que esteja com um tricóptero doido rodando / rotacionando no eixo Z sem rumo.

Desculpem pelas fotos. O tricóptero zanzou tanto pela grama e pela terra que o LCD ficou sujo por dentro... ; )

Abs!
Otávio

Para ver todos os posts deste projeto, você pode clicar no marcador "tricarneiro".

domingo, 17 de agosto de 2014

Tricarneiro, o drone - Ep. 5 - Controladora e Receptor

Vídeo contendo a experiência de ligar a placa controladora (KK2.1) pela primeira vez.

No YouTube: http://youtu.be/N87zJ9Pv_U0



O vídeo mostra a conexão da placa controladora ao primeiro ESC (que a energiza) e ao receptor (RX do rádio Turnigy 9X).

Para ver todos os posts deste projeto, você pode clicar no marcador "tricarneiro".

terça-feira, 3 de junho de 2014

Tricarneiro, o drone - Ep. 4 - Fiação e Solda

Vídeo sobre a colocação dos componentes eletrônicos e fios na estrutura do drone.

O vídeo mostra uma primeira montagem provisória e ensina como fazer o cabo que serve de hub para distribuição da energia que sai da bateria para os ESC's.

A placa controladora (KK2.1) é alimentada pelos ESC's e alimenta o servo na cauda do tricóptero.




Para ver todos os posts deste projeto, você pode clicar na tag "tricarneiro" logo abaixo.

Tricarneiro, o drone. Ep. 3 - Estrutura

Neste vídeo, eu queria mais mostrar o processo de montagem da estrutura do drone do que efetivamente falar alguma coisa. Para o vídeo não ficar muito chato, fiz alguns "timelapses", vídeos montados a partir de fotos tiradas a intervalos regulares.

O vídeo mostra a marcação dos buracos do tricóptero, a pintura das peças que formam os "trens de pouso" do drone, a furação e a montagem.



Para ver todos os posts deste projeto, você pode clicar no marcador "tricarneiro".

sexta-feira, 2 de maio de 2014

Tricarneiro, o drone. Ep. 2 - Eletrônica Básica

No meu post anterior eu tinha falado que ia faltar uma coisinha ou outra para montar o meu tricóptero, o Tricarneiro. Pois bem, faltou mesmo.

O site da Hobby King indicava a seguinte especificação para o Electronic Speed Controller (ESC) que comprei:

Specs:
Current Draw: 12A Continuous
Voltage Range: 2-4s Lipoly
BEC: 0.5A Linear
Input Freq: 1KHz
Firmware: afro_nfet.hex
Discharge wire/plugs: 16AWG/Male 3.5mm
Motor wire/plugs: 16AWG/Female 3.5mm
Weight: 20.3g (Included wire, plug, heat shrink)
Size: 29.5 x 22.6 x 6mm

A sacanagem está na parte dos plugs. Reparem que eles falam em 3.5mm. Isso aí me quebrou as pernas... Os plugs que vieram com os ESC's são de 2mm. E o pior (melhor?) é que os conectores são muito bem feitos, o que tira qualquer ideia de arrancá-los fora para colocar outros.

Um amigo sugeriu tirar os plugs e conectar o ESC diretamente ao drone com solda mesmo, mas achei essa solução muito permanente. Além disso, iria diminuir um pouco as possibilidades didáticas da brincadeira.

Resultado: procurei na internet os tais conectores bullet de 2mm. Encontrei alguns fornecedores no MercadoLivre. O preço não era ruim: R$ 2,99 cada par (com um macho e uma fêmea). O problema é que eu tinha pressa. Comprei logo 10 pares e paguei uns R$ 40 reais de frete. Ou seja, 70 conto em uns pedacinhos de metal.

Outra coisa que tive que comprar adicional foram os anéis de borracha para prender as hélices aos motores. Eu não sabia o que era um prop saver (salva hélice) e acabei descobrindo. É um suporte para hélices que fica preso ao motor e que permite prender a hélice a ele por um anel de borracha. O motor que comprei, um Turnigy Park300, já vem com o prop saver, mas não com o anel. Tudo bem, foi barato. R$ 13,79 por 10 unidades. E fui buscar no fornecedor, então não paguei frete.

Comprei uns fios também. O site da SoldaFria tem uma tabela muito interessante indicando que tipo de fio você precisa conforme a corrente do seu circuito. Por aquela tabela, vi que um fio de 1mm de espessura (18AWG) aguenta uma corrente de 16A. Comprei 10m de cada cor, a R$ 2,40 cada. Com o frete, uns 60 reais de fio.

No vídeo, eu mostro como usar o rádio, incluindo como resolver o erro "Switch Error" do transmissor (um Turnigy 9x) e como energizar o receptor. Não vou fazer suspense. No transmissor você vira todas as alavancas para frente e o receptor você conecta a um ESC ligado à bateria.



Vocês vão reparar no vídeo que o motor não funciona na minha primeira tentativa. Acho que o ESC precisa ser "armado" para iniciar. Usualmente, colocar o acelerador no mínimo faz esse trabalho. Eu teria que estudar um pouco mais essa história para dizer com certeza. Se souberem, por favor comentem aqui.

No próximo post devo começar a montar a estrutura. Ainda tenho bastante trabalho pela frente, então continuem acompanhando.

Para ver todos os posts deste projeto, você pode clicar na tag "tricarneiro" logo abaixo.

Abraço!

terça-feira, 22 de abril de 2014

Tricarneiro, o drone. Ep. 1 - Compras

Comecei um projeto novo!

Estou montando um drone. É um tricóptero, um multirotor. Algo como um helicóptero com três  hélices, por assim dizer.

Montar um negócio desse exige muito estudo, então vou levar muito tempo até tirar ele do chão. Assim, pensei em ir compartilhando com vocês o aprendizado que eu for adquirindo ao longo da empreitada.

O primeiro desafio que encontrei foi escolher o que eu precisava comprar. Já existem drones completos à venda, prontos para voar (os RTF, ready-to-fly), mas na época em que comecei, não havia nenhum tricóptero desse modelo. Os mais comuns são os quadricópteros e eu queria um tri. Assisto muito os vídeos do canal Flite Test e em um vídeo deles fizeram uma comparação entre quads e tris e preferiram os tri para filmagens em função do tipo de movimento que fazem. Me convenceram!

Acabei escolhendo o quadro de tricóptero fornecido pela própria Flite Test, o Bat Bone. Um dos motivos foi contribuir para a continuidade do canal, que assisto muito. Outro motivo foi a facilidade de já ter ali na página do produto as recomendações de peças para o restante, que comprei na HobbyKing.

HobbyKing é um loja online muito boa para comprar equipamentos para aeromodelismo e afins. A minha lista completa de compras vai aqui embaixo, mas por enquanto vocês podem assistir o primeiro vídeo desta série, em que abro as caixas e mostro tudo o que chegou.


Os pacotes levaram uma eternidade para chegar... Pedi o primeiro (Flite Test, dos EUA) em 30 de novembro de 2013 e o segundo (HobbyKing, vindo das Ilhas Fiji) em 19 de janeiro de 2014. Os dois acabaram chegando juntos, no início de abril de 2014. Ou seja, uns 4 meses depois da compra...

O melhor de tudo (só que não) é que eles foram tributados. Tive que pagar os famosos 60% sobre o valor do produto + frete. Vejam aqui a fatura completa:

HobbyKing
ItemQtdePreço
Turnigy 9X 9Ch Transmitter w/ Module & 8ch Receiver (Mode 2) (v2 Firmware)*JIT-Item (this item takes 3-5 days to dispatch) 1  US$53.82  
JR Transmitter Neck Strap 1  US$3.22  
IMAX B6-AC Charger/Discharger 1-6 Cells (GENUINE) 1  US$39.99  
Nylon XT60 Connectors Male/Female (5 pairs) GENUINE 1  US$3.25  
3.5mm 3 wire Bullet-connector for motor (5pairs/bag) 1  US$4.71  
Hobbyking KK2.1 Multi-rotor LCD Flight Control Board With 6050MPU And Atmel 644PA 1  US$29.95  
Afro ESC 12Amp Multi-rotor Motor Speed Controller (SimonK Firmware) 3  US$9.99  
Turnigy Park300 Brushless Outrunner 1380kv 3  US$13.99  
Turnigy 2200mAh 3S 20C Lipo Pack 2  US$7.89  
Lipoly Charge Bag 23 x 30cm 2  US$2.10  
Peel-n-stick foam double sided tape 10x5inch 4mm thick 1  US$1.19  
Y Adapter For KK2.0 Super Bright LED and Buzzer 1  US$1.95  
Scorpion Lipoly Lock Strap 205mm (Small) x 3 1  US$5.28  
Linkage Stopper D1.8mm (10pcs) 1  US$2.95  
Afro ESC USB Programming Tool 1  US$7.21  
TGY-375DMG Metal gear Digital Servo w/ Heat Sink 2.3kg / .11sec / 11.5g 1  US$18.82  
8045 SF Props 2pc CW 2 pc CCW Rotation (Orange) 2  US$2.79  
8045 SF Props 2pc CW 2 pc CCW Rotation (Green) 2  US$2.79  
Total Itens  26  US$211.89  
Frete  1  US$61.25  
Total Hobby King      US$336.67  

FliteTest
ItemQtdePreço
Bat Bone Tri 370 Kit1  US$79.00  
Desconto1  -US$11.85  
Frete1  US$20.65  
Total Flite Test      US$87.80  

Receita Federal
OrigemValor do BemFreteCotação DólarValor TributávelImposto
Flite TestUS$ 79US$ 8R$ 2,283R$ 198,62R$ 119,17
Hobby KingUS$ 300  R$ 2,2603R$ 678,09R$ 406,85
Total Receita   R$ 526,02

O total geral em reais dá para tirar dessa última tabela, somando os valores tributáveis e o imposto. Deu R$ 1.402,73. Uh! Brincadeira cara!

Claro que ainda vai faltar uma coisinha ou outra, mas vou atualizando nos próximos posts...

Abraço!

ATUALIZAÇÃO (01/05/2014): Coloquei legendas em inglês no vídeo. Achei legal o processo, depois ensino vocês!

Para ver todos os posts deste projeto, você pode clicar na tag "tricarneiro" logo abaixo.

sexta-feira, 31 de janeiro de 2014

Olho de LCD com Arduino e Nokia 5110 - #sucesso

E... voilá!!


Consegui fazer o Olho de LCD usando um display Nokia 5110 e o Arduino!!!


De início eu havia pensado em gerar um arquivo bitmap (BMP) e convertê-lo depois em código usando uma ferramenta automatizada. Ou pelo menos foi o que eu escrevi que ia fazer no meu último post...

Acabei fazendo uma coisa bem diferente... Foi um trabalho mais braçal, mas deu certo.

Primeiro, marquei com uma canetinha vermelha as divisas das linhas do display, a cada 8 quadradinhos. O display recebe os dados a exibir na forma de bytes. Cada byte contém oito bits, então os dados chegam ao display na forma de linhas com oito bits de espessura. Foram essas linhas que marquei.

Para cada uma das 6 linhas, montei uma sequência de bytes. Para ficar bem claro no código, escrevi os bytes usando o sistema binário, assim:

0b00000000 //uma linha em branco
0b11111111 //uma linha preta

O "0b" no início diz ao Arduino que estou usando o sistema binário, ou seja, só zeros e uns.
Tive que escrever o correspondente de 0 ou 1 para cada quadradinho da grade que forma o display. Ou seja, 84 x 48 = 4032. Claro que usei um bocado de Ctrl + C, Ctrl + V e escrevi em linhas de 8 bits, então foram apenas 504 linhas de código para descrever o desenho... ;)
O código inteiro está aí embaixo, usem à vontade!


Se fizerem melhorias para ele olhar para os lados, piscar, etc, por favor compartilhem! Eu quero fazer isso também, mas se forem mais rápidos que eu, vai me poupar um bocado de trabalho!

Abraços!


//Olho de LCD - v1
//Controlador de Display LCD Nokia 5110 (84x48 pixels)
//em 31 de janeiro de 2014
//Mais informacoes: umcarneiro.blogspot.com
//Licenca: MIT (use como quiser!)

//Pinos utilizados no arduino
#define PIN_SCE   7  //pino 2 do display
#define PIN_RESET 6  //pino 1 do display
#define PIN_DC    5  //pino 3 do display
#define PIN_SDIN  4  //pino 4 do display
#define PIN_SCLK  3  //pino 5 do display

//Tamanho do LCD em pixels:
#define LCD_X     84
#define LCD_Y     48

byte linhaUm[84] = {
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //5
      0b00000000,
      0b00000001,
      0b00000010,
      0b00000100,
      0b00000100,  //10
      0b00001000,
      0b00001000,
      0b00010000,
      0b00100000,
      0b00100000,  //15
      0b00100000,
      0b01000000,
      0b01000000,
      0b01000000,
      0b01000000,  //20
      0b01000000,
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,  //25
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,  //30
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,  //35
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,  //40
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,  //45
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,  //50
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,  //55
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,  //60
      0b10000000,
      0b10000000,
      0b10000000,
      0b10000000,
      0b01000000,  //65
      0b01000000,
      0b00100000,
      0b00100000,
      0b00010000,
      0b00010000,  //70
      0b00001000,
      0b00001000,
      0b00000100,
      0b00000010,
      0b00000010,  //75
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //80
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000
};

byte linhaDois[84] = {
      0b00000000,
      0b00000011,
      0b00001100,
      0b00110000,
      0b01000000,  //5
      0b10000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //10
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //15
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //20
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //25
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //30
      0b00000000,
      0b00000000,
      0b00000001,
      0b00000011,
      0b00000111,  //35
      0b00000111,
      0b00001111,
      0b00001111,
      0b00001110,
      0b00011110,  //40
      0b00011111,
      0b00011111,
      0b00011111,
      0b00011111,
      0b00011111,  //45
      0b00011111,
      0b00011111,
      0b00011111,
      0b00011111,
      0b00011111,  //50
      0b00011111,
      0b00011111,
      0b00011111,
      0b00011111,
      0b00011111,  //55
      0b00011111,
      0b00011111,
      0b00011111,
      0b00001111,
      0b00001111,  //60
      0b00001111,
      0b00001111,
      0b00001111,
      0b00001111,
      0b00000111,  //65
      0b00000111,
      0b00000011,
      0b00000001,
      0b00000000,
      0b00000000,  //70
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //75
      0b00000000,
      0b10000000,
      0b01000000,
      0b00100000,
      0b00010000,  //80
      0b00001000,
      0b00000110,
      0b00000001,
      0b00000000
};

byte linhaTres[84] = {
      0b11111111,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //5
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //10
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //15
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //20
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //25
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00001111,  //30
      0b00111111,
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,  //35
      0b10001111,
      0b00000111,
      0b00000111,
      0b00000011,
      0b00000011,  //40
      0b00000011,
      0b00000111,
      0b00001111,
      0b11111111,
      0b11111111,  //45
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,  //50
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,  //55
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,  //60
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,  //65
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,
      0b00111111,  //70
      0b00001111,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //75
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //80
      0b00000000,
      0b00000000,
      0b10000000,
      0b01111111
};

byte linhaQuatro[84] = {
      0b11111000,
      0b00000110,
      0b00000001,
      0b00000000,
      0b00000000,  //5
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //10
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //15
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //20
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //25
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b11100000,  //30
      0b11111000,
      0b11111100,
      0b11111111,
      0b11111111,
      0b11111111,  //35
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,  //40
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,  //45
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,  //50
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,  //55
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,  //60
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111001,
      0b11111001,  //65
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111111,
      0b11111110,  //70
      0111111000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //75
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //80
      0b00000000,
      0b00000000,
      0b00001111,
      0b11110000
};

byte linhaCinco[84] = {
      0b00000000,
      0b00000000,
      0b00000000,
      0b11000000,
      0b00110000,  //5
      0b00001100,
      0b00000010,
      0b00000001,
      0b00000000,
      0b00000000,  //10
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //15
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //20
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //25
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //30
      0b00000000,
      0b00000000,
      0b00000000,
      0b10000000,
      0b11000000,  //35
      0b11000000,
      0b11100000,
      0b11100000,
      0b11110000,
      0b11110000,  //40
      0b11110000,
      0b11111000,
      0b11111000,
      0b11111000,
      0b11111000,  //45
      0b11111000,
      0b11111000,
      0b11111000,
      0b11111000,
      0b11111000,  //50
      0b11111000,
      0b11111000,
      0b11111000,
      0b11111000,
      0b11111000,  //55
      0b11111000,
      0b11111000,
      0b11111000,
      0b11111000,
      0b11111000,  //60
      0b11110000,
      0b11110000,
      0b11110000,
      0b11110000,
      0b11100000,  //65
      0b11100000,
      0b11000000,
      0b11000000,
      0b10000000,
      0b00000000,  //70      
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //75
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000011,
      0b00000100,  //80
      0b00011000,
      0b01100000,
      0b10000000,
      0b00000000
};

byte linhaSeis[84] = {
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000,  //5
      0b00000000,
      0b00000000,
      0b00000000,
      0b10000000,
      0b01000000,  //10
      0b00100000,
      0b00010000,
      0b00010000,
      0b00001000,
      0b00001000,  //15
      0b00001000,
      0b00000100,
      0b00000100,
      0b00000100,
      0b00000010,  //20
      0b00000010,
      0b00000010,
      0b00000010,
      0b00000010,
      0b00000001,  //25
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000001,  //30
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000001,  //35
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000001,  //40
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000001,  //45
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000001,  //50
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000001,  //55
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000001,  //60
      0b00000001,
      0b00000001,
      0b00000001,
      0b00000010,
      0b00000010,  //65
      0b00000010,
      0b00000010,
      0b00000010,
      0b00000010,
      0b00000100,  //70
      0b00000100,
      0b00000100,
      0b00001000,
      0b00010000,
      0b00100000,  //75
      0b00100000,
      0b01000000,
      0b10000000,
      0b00000000,
      0b00000000,  //80
      0b00000000,
      0b00000000,
      0b00000000,
      0b00000000
};

void setup(void)
{
  pinMode(PIN_SCE, OUTPUT);   // Inicializa os pinos...
  pinMode(PIN_RESET, OUTPUT);
  pinMode(PIN_DC, OUTPUT);
  pinMode(PIN_SDIN, OUTPUT);
  pinMode(PIN_SCLK, OUTPUT);
  digitalWrite(PIN_RESET, LOW); //RESET no controlador
  digitalWrite(PIN_RESET, HIGH);
  LcdWrite(LOW, 0x21 );  // Function set: PD=0 (On); V=0 (Horizontal); H=1 (Extended instruction set)
  LcdWrite(LOW, 0xBA );  // Define o LCD Vop (Contraste). //XXXXXXXXXXXXXXX
  LcdWrite(LOW, 0x04 );  // Define o coeficiente de temperatura (??)
  LcdWrite(LOW, 0x14 );  // LCD bias mode 1:48  (??)
  LcdWrite(LOW, 0x20 );  // Function set: PD=0 (On); V=0 (Horizontal); H=0 (Basic instruction set)
  LcdWrite(LOW, 0x0C );  // Display control = 10 (Normal)
  
  limpaTela();
  
  desenhaLinha(linhaSeis);
  desenhaLinha(linhaCinco);
  desenhaLinha(linhaQuatro);
  desenhaLinha(linhaTres);
  desenhaLinha(linhaDois);
  desenhaLinha(linhaUm);   
}
  
void limpaTela(void) {
  //Percorre todas as posicoes
  for (int index = 0; index < LCD_X * LCD_Y / 8; index++)
  {
    LcdWrite(HIGH, 0);
  }
}

void desenhaLinha(byte linha[]) {
  //Percorre as colunas
  for (int coluna = 0; coluna < LCD_X; coluna++)
  {
    LcdWrite(HIGH, linha[coluna]);
  }
}


//Cuida da burocracia: envia o comando ou dado seguindo o protocolo do chip
void LcdWrite(byte dc, byte data)
{
  digitalWrite(PIN_DC, dc); //define se vai mandar dado ou comando
  digitalWrite(PIN_SCE, LOW); //ativa o chip para receber dados
  shiftOut(PIN_SDIN, PIN_SCLK, MSBFIRST, data); //envia um bit de cada vez, comecando pela esquerda
  digitalWrite(PIN_SCE, HIGH); //desativa o envio de dados
}

void loop(void)
{  
  //nada
}


Você pode ver todas as etapas deste projeto usando este link, ou clicando no marcador "olho_de_lcd", abaixo.

segunda-feira, 27 de janeiro de 2014

Criando um bitmap para LCD Gráfico

Há algum tempo comecei um projeto para fazer um olho de brinquedo usando um LCD Gráfico Nokia 5110. A primeira tentativa falhou, mas depois entendi como o display funciona. Resta agora colocar o meu desenho nele.

Mas que desenho?

Pois bem, como é que você desenha algo para ficar bem em determinada resolução? Eu tive que testar imprimindo uma grade na resolução do display (84x48) para rabiscar em cima.

Claro que eu poderia criar uma imagem de 84 por 48 pixels e rabiscar no computador, mas de que jeito minha filha e nossa cachorrinha participariam do projeto?


Então, para permitir mais participação, criei a grade no computador e imprimi para desenhar. Minha primeira escolha de software seria o Inkscape, mas achei mais fácil fazer no Gimp.

A primeira coisa que descobri é que uma grade de 24 por 24 pixels permite você numerar os quadrados numa boa, então usei esse tamanho. Assim, minha imagem tinha que ter 24 vezes 84 de altura e 24 vezes 48 de largura, o que dá 1152 x 2016 pixels.

Com a imagem no tamanho certo, basta criar a grade. Vá em:
Filtros -> Renderizar -> Padrão -> Grade



Achou o caminho estranho? Pois é, eu também achei...

Nas opções da grade você só precisa alterar os campos  de "Espaçamento". O padrão é 16x16, mas eu usei 24x24, como mencionei acima.

Salvei um arquivo PNG e mandei imprimir a partir do visualizador de imagens. Não sei se dava para imprimir direto do Gimp. Estou tão acostumado a fazer desse jeito que nem tentei...

O resultado final está aí do lado. Talvez, se eu tivesse usado um scanner, daria para pegar a imagem direto e redimensionar para 48x84 e já jogar em um conversor de bitmap para bytes e partir para o abraço, mas...

Não tenho um scanner e o conversor de bitmaps indicado pela Sparkfun está fora do ar... Isso quer dizer que ainda terei mais algum trabalho com esse projeto e que teremos mais posts no blog sobre o assunto.

Nos vemos em breve!

Você pode ver todas as etapas deste projeto usando este link, ou clicando no marcador "olho_de_lcd", abaixo.

quinta-feira, 16 de janeiro de 2014

LCD Nokia 5110 com Arduino #sucesso

No meu post anterior eu falei que comprei um display LCD Nokia 5110 no MercadoLivre e, inicialmente não consegui fazê-lo funcionar... Depois eu atualizei o post dizendo que ele funcionou e fiquei de dar mais detalhes depois. Bom, aqui estão os detalhes!

Display Nokia 5110 sobre datasheet Philips PCD8544

Apesar de todo mundo se referir ao display como Nokia 5110, a parte importante para conhecer é o controlador que ele tem dentro, que na verdade é feito pela Philips! O controlador/driver é um Philips PCD8544.

O datasheet dele é bem extenso (32 páginas), mas você não precisa se preocupar, está numa linguagem bem acessível e tem até um exemplo de como desenhar uma palavra na tela, mostrando o que você deve enviar, bit a bit (página 22).


Para tentar entender o funcionamento do módulo, imprimi as páginas 14 e 22 e ainda montei uma "cola" para anotar o que cada byte representava em bits.


O problema que eu estava tendo com este módulo parecia estar na definição do contraste, então criei o código abaixo para vocês testarem o módulo de vocês. O que ele faz é desenhar uma barra que vai crescendo a medida que o contraste vai aumentando.

Este gif animado dá uma ideia do resultado. O contraste ideal é aquele em que a barra fica bem escura sobre um fundo claro. Se o fundo do seu LCD escurecer, é porque você passou da conta e deve diminuir um pouquinho.


//Controlador de Display LCD Nokia 5110 (84x48 pixels)
//em 13 de janeiro de 2014
//Mais informacoes: umcarneiro.blogspot.com
//Licenca: MIT (use como quiser!)

//Pinos utilizados no arduino
#define PIN_SCE   7  //pino 2 do display
#define PIN_RESET 6  //pino 1 do display
#define PIN_DC    5  //pino 3 do display
#define PIN_SDIN  4  //pino 4 do display
#define PIN_SCLK  3  //pino 5 do display

//Tamanho do LCD em pixels:
#define LCD_X     84
#define LCD_Y     48

//Estas variaveis restringem o menor e o maior contraste a ser testado
//Se sua tela estiver muito escura desde o inicio do teste, diminua este valor
const int MIN_CONTRAST = 175; //tem que ser maior que 128
//Se sua tela estiver muito clara no fim do teste, aumente este valor
const int MAX_CONTRAST = 200; //tem que ser menor que 255


void setup(void)
{
  pinMode(PIN_SCE, OUTPUT);   // Inicializa os pinos...
  pinMode(PIN_RESET, OUTPUT);
  pinMode(PIN_DC, OUTPUT);
  pinMode(PIN_SDIN, OUTPUT);
  pinMode(PIN_SCLK, OUTPUT);
  digitalWrite(PIN_RESET, LOW); //RESET no controlador
  digitalWrite(PIN_RESET, HIGH);
  LcdWrite(LOW, 0x21 );  // Function set: PD=0 (On); V=0 (Horizontal); H=1 (Extended instruction set)
  LcdWrite(LOW, 0xBA );  // Define o LCD Vop (Contraste). //XXXXXXXXXXXXXXX
  LcdWrite(LOW, 0x04 );  // Define o coeficiente de temperatura (??)
  LcdWrite(LOW, 0x14 );  // LCD bias mode 1:48  (??)
  LcdWrite(LOW, 0x20 );  // Function set: PD=0 (On); V=0 (Horizontal); H=0 (Basic instruction set)
  LcdWrite(LOW, 0x0C );  // Display control = 10 (Normal)
  
  //Clear - apaga todas as posicoes
  for (int index = 0; index < LCD_X * LCD_Y / 8; index++)
  {
    LcdWrite(HIGH, 0x00); //bit 0 em todo mundo!
  }

}

//Cuida da burocracia: envia o comando ou dado seguindo o protocolo do chip
void LcdWrite(byte dc, byte data)
{
  digitalWrite(PIN_DC, dc); //define se vai mandar dado ou comando
  digitalWrite(PIN_SCE, LOW); //ativa o chip para receber dados
  shiftOut(PIN_SDIN, PIN_SCLK, MSBFIRST, data); //envia um bit de cada vez, comecando pela esquerda
  digitalWrite(PIN_SCE, HIGH); //desativa o envio de dados
}

//desenha uma barra repetindo o byte informado
void desenhaBarra(int largura, byte caracter)  
{
  //Coloca o cursor no local correto
  LcdWrite( 0, 0x80 | 0);  // Coluna 0
  LcdWrite( 0, 0x40 | 2);  // Linha 2

  //barra horizontal
  for (int index = 0; index < largura; index++)
  {
    LcdWrite(HIGH, caracter);
  }
}

void loop(void)
{  
  //dentro dos limites que estabelecemos, define o contraste a mostrar
  for (int contrast = MIN_CONTRAST; contrast < MAX_CONTRAST; contrast++)
  {  
    LcdWrite(LOW, 0x21 );  // Function set: PD=0 (On); V=0 (Horizontal); H=1 (Extended instruction set)
    LcdWrite(LOW, contrast );  // Define o contraste (VOP)
    
    //define a largura da barra proporcional ao contraste
    int largura = map(contrast, MIN_CONTRAST, MAX_CONTRAST, 0, LCD_X); 

    LcdWrite(LOW, 0x20 );  // Function set: PD=0 (On); V=0 (Horizontal); H=0 (Basic instruction set)
    LcdWrite(LOW, 0x0C );  // Display control = 10
  
    //desenha a barra horizontal na largura que definimos
    desenhaBarra(largura, 0x7f);
    delay(350); //dah um tempo para podermos ver o resultado
  }
  
  //desenha uma barra invisivel da largura da tela
  desenhaBarra(LCD_X, 0x00); //ou seja, apaga a barra!
}


Juro que este foi o código mais simples que eu consegui fazer! Enchi de comentários para ver se conseguia torná-lo inteligível. Defini o contraste usando números decimais de propósito, para facilitar a leitura.  Tem um ótimo conversor de números entre binário, decimal e hexa nesta página. Eu usei um bocado para tentar entender o que estava acontecendo.

O circuito ficou assim:



Pino LCDResistorArduinoCor
1-RST10kPino 6Vermelho
2-CE10kPino 7Azul
3-DC10kPino 5Amarelo
4-DIN10kPino 4Verde
5-CLK10kPino 3Azul
6-VCC-3.3vVermelho
7-LIGHT330RGNDAzul
8-GND-GNDPreto

O código que eu tinha usado da outra vez usava, obrigatoriamente os pinos 11 e 13, mas este é mais simples e não tem essa exigência.

Repare também que o backlight (pino 7 do LCD) foi para o GND. Confesso que não entendi bem a lógica disso, já que o backlight se acende quando colocamos +3V direto no pino 7 e GND no pino 8.


O desenho do módulo de LCD no Fritzing eu fiz por conta própria. Se quiser o arquivo ou aprender a fazer você mesmo, leia este outro post.

Espero que vocês consigam colocar as suas telinhas para funcionar!

Quem sabe em um próximo post a minha já terá virado um olho de brinquedo?

Aguardem!

UPDATE: Desenhei o olho para colocar no LCD. Vejam neste outro post.

Você pode ver todas as etapas deste projeto usando este link, ou clicando no marcador "olho_de_lcd", abaixo.

sexta-feira, 10 de janeiro de 2014

Como criar um componente para o Fritzing

Quando fui documentar o meu projeto de criar um olho de brinquedo usando um display LCD Nokia 5110, descobri que o Fritzing não tem um desenho deste display. E agora? Como fazer para desenhar?

A referência oficial do Fritzing que achei na internet dizia estar desatualizada e mandava ir procurar no blog deles, mas não tinha um link direto.


Na verdade, a instrução estava desatualizada por existir um novo editor de partes dentro do Fritzing desde a versão 0.7.9, mas a versão que eu tinha (0.6.3, a que você encontra na Central de Programas do Ubuntu) ainda não vinha com esse editor.

Fritzing 0.8.5
Dei uma pesquisada e o editor novo me pareceu bem melhor que o anterior, então baixei a versão atual do Fritzing, a 0.8.5. Se estiver usando o Ubuntu, recomendo você baixar a versão disponível na Central de Programas do Ubuntu primeiro e depois instalar essa, isso garante que as dependências estarão atendidas.

O post do blog do Fritzing que detalha como usar o novo editor de componentes está neste link:
http://blog.fritzing.org/2012/10/09/new-parts-editor-released/

Tudo o que escrevi aqui aprendi lendo esse post, então se tiverem dúvidas, vão ali primeiro.

O editor de componentes (parts) do Fritzing precisa começar sempre de um componente existente. Como estamos trabalhando com um display de LCD, faz todo sentido partir de outro display de LCD. O Nokia 5110 é um display gráfico, então eu inseri um display gráfico 128 x 64.

A partir daí, você pode clicar no componente com o botão direito e selecionar Editar ou ir em Componente -> Editar (Criador de Novos Componentes).

Para criar as imagens, eu exportei para SVG o desenho do display de 128x64 (verde) e o abri no Inkscape. O desenho já chegou no Inkscape com medidas corretas (para um display grande). Usando medidas em mm, consegui redesenhar o meu display. Tomei alguns cuidados para conseguir importá-lo de volta no Fritzing:
  • Não mexi na posição inicial do desenho (que começa nas coordenadas 0,0);
  • Alterei o tamanho total do desenho SVG (Propriedades do Documento) e o deixei do tamanho do meu componente (43,5x43mm);
  • Não mexi nos pinos que já existiam, só removi os que estavam sobrando.
O que eu fiz foi basicamente desagrupá-lo todo, mudar a cor, apagar vários dos pinos e aplicar as medidas que eu mesmo obtive com uma régua. Evitei tentar colocar os pinos de cima, já que não iria precisar deles.

Ao voltar para o Fritzing, carreguei minha imagem (Ctrl+O) e ele magicamente já identificou os pinos, deixando os que apaguei desmarcados (não encontrados).


Fui até a aba "Conectores" e apaguei os conectores de 1 a 12 (os mesmos que eu tinha apagado do desenho) e reajustei os demais conforme a realidade (1 a 8, RST, CE, DC, etc.)

Na aba "Metadado", preenchi as informações sobre o componente. Na aba "Ícone", fui em Arquivo -> "Reusar imagem do protoboard".


Para a aba "PCB" você tem que gerar um novo arquivo SVG. Você faz o mesmo processo da visão Protoboard: exportar o desenho existente e editar.

A única coisa diferente é que os pontos de solda têm que estar em um grupo chamado "copper0". Para isso, você agrupa os circulos que representam os pontos de solda (Ctrl+G) e edita o nome do grupo apertando Ctrl+Shift+X e alterando a propriedade "id" para "copper0". Ctrl+Enter grava a alteração do nome no campo. Salve o arquivo e o importe no Fritzing que ele vai reconhecer.


A aba Esquemático você pode fazer como quiser, basta usar as fontes corretas. Se não usar, não tem problema, o Fritzing troca para você.

Pronto! Agora você já pode usar o componente que você desenhou no seu projeto!


O componente que eu criei você pode pegar aqui e usar como quiser.

UPDATE: No dia 16/01/2014, postei um exemplo de como colocar o display para funcionar, com código e tudo. Veja aqui.

Você pode ver todas as etapas deste projeto usando este link, ou clicando no marcador "olho_de_lcd", abaixo.