Recentemente, os chamados velocímetros digitais de bicicleta (computadores para ciclistas) se espalharam entre os acessórios de bicicleta. Esses dispositivos são capazes de medir muitos parâmetros, sendo os principais a velocidade e a distância. O princípio da medição da velocidade baseia-se no cálculo do período de rotação da roda e a distância é calculada com base na medição do número dessas rotações. Freqüentemente, o sensor de rotação da roda é um interruptor de palheta em conjunto com um ímã no raio da roda. Dependendo da funcionalidade, o preço desses dispositivos varia muito. O velocímetro de bicicleta mais barato pode ser adquirido por cerca de 500 p.
Eu sempre tive o desejo de ter um dispositivo semelhante. Ao mesmo tempo, formulei vários requisitos próprios, que deveriam atender. Antes de tudo, eu realmente queria ver um gráfico das mudanças de velocidade, dependendo da distância ou do tempo acumulado durante um curto período de tempo. Além disso, para registrar (registrar) medições em um dispositivo de armazenamento para posterior transferência de dados estatísticos para um computador, sua visualização mais detalhada. Os modelos baratos não atendem totalmente aos meus requisitos, mas não quero pagar em excesso por modelos caros.
Com base no exposto, decidi criar meu próprio velocímetro de bicicleta com base no microcontrolador ATmega8. Havia muitas perguntas, em particular sobre os periféricos usados. Eu acidentalmente me deparei com artigos sobre o uso da tela do outrora popular telefone celular Nokia 3310. Depois de ler a ficha técnica e me certificar de que era simples de operar, não tive dúvidas de que o velocímetro seria fabricado no corpo do telefone mencionado com seu próprio monitor. O caso é muito bom, e o dispositivo em si não é difícil de encontrar.

Como uma ROM para registrar estatísticas de medição, decidi colocar uma ROM clássica 24XX512 (512 Kbps), controlada pela interface I2C. Eu não me incomodei com o uso de um cartão de memória SD / MMC. Outra função importante no dispositivo é o relógio. Eles servem para vincular alguns parâmetros específicos medidos (por exemplo, velocidade máxima) à data e hora e também são necessários para registrar registros de data e hora nas estatísticas. Como relógio, usei um chip RTC (clock em tempo real) separado do microcontrolador, que possui energia de bateria independente e também se comunica com o controlador via I2C.
Eu implementei requisitos secundários adicionais na funcionalidade do dispositivo na fase de criação do programa. Isso inclui todos os tipos de questões organizacionais: o número de botões envolvidos, o local na exibição de vários elementos, a navegação na interface e assim por diante. Em termos de navegação, decidi antecipadamente não complicar o programa, por exemplo, não implementar o menu de configurações, em particular as configurações de data e hora. O relógio é acertado uma vez. O relógio está correndo independentemente no chip RTC, graças a um quartzo de 32.768 KHz e uma bateria que dura muito tempo. As configurações de data e hora são realizadas através da interface UART do velocímetro, conectada à porta COM do computador com um clique. Através da mesma interface, era para ler dados estatísticos da ROM para um computador. Por tudo isso, você deve escrever o programa apropriado para o computador. No entanto, como demonstrou mais prática, este último teve que ser abandonado. Em primeiro lugar, havia o problema de implementar a recepção de dados do controlador para o computador na fase de gravação de um programa de computador. E, ainda mais significativamente, o volume do programa para o controlador aumentou. Era muito mais interessante colocar a ROM (no compartimento SMIC SOIC-8) em uma plataforma removível, proporcional ao cartão SIM e usar o slot livre apropriado no telefone celular. Para fazer isso, é necessário fabricar um leitor de ROM baseado em um leitor SIM, de acordo com um dos esquemas conhecidos do programador de ROM I2C. Como se viu depois, esta decisão não causou inconvenientes desnecessários.
Outra questão importante é a saída de informações simbólicas (inclusive digitais) em uma tela gráfica. Isso requer informações gráficas sobre um símbolo específico. Esta informação está intimamente relacionada a um parâmetro como o tamanho da fonte exibida. Para exibir o parâmetro principal, a velocidade do movimento, para melhor clareza, é desejável usar uma fonte grande. No entanto, como será mostrado mais adiante, essas informações gráficas de dez dígitos não caberão na memória do MK, e o uso da mesma ROM externa mais espaçosa diminuirá a velocidade de desenhar a fonte. Eu decidi usar uma fonte com uma altura de 8 pontos como a maior fonte. Peguei as informações gráficas para essa fonte do arquivo "8X8.FNT" de algum programa do MS DOS, depois de desvendar sua estrutura e fazer mais processamento.

Como mais tarde se revelou na prática, esse tamanho é suficiente para maior clareza de velocidade. Como tamanho da fonte adicional, escolhi o tamanho 3x5 e desenhei independentemente os gráficos para os números desse tamanho. Esses pequenos números exibem parâmetros adicionais: data / hora, velocidade média e máxima, caminho.
As informações gráficas de ambas as fontes são armazenadas em determinadas matrizes bidimensionais. Cada elemento da matriz, com 1 byte de tamanho, indica a distribuição de pixels de uma coluna específica de um dígito específico. Para letras grandes, 8 colunas são alocadas para cada dígito e 3 para 3. Para letras pequenas, tamanho 3X5, a altura formal não é 5, mas 8 pontos (arredondado a um byte). Isso permite que você pré-organize a localização da fonte de 5 posições na área de 8 posições na direção vertical usando um dos 4 métodos possíveis. Esses fatos são bem exibidos na figura abaixo, que demonstra a modelagem de gráficos para os dois primeiros dígitos dessa fonte. O Excel é conhecido pela modelagem. Os dados iniciais são o arranjo de "unidades" nos campos apropriados para os gráficos desejados. Destas, as fórmulas calculam os valores das matrizes, até o código da linguagem C, que pode ser copiado posteriormente no texto do programa para o microcontrolador.

Agora falaremos sobre os recursos de controle da tela usada. Essa tela é monocromática e suas dimensões são 84 por 48 pixels. O controle de exibição do MK é realizado através da interface SPI. Os bytes transmitidos pelo SPI são interpretados na exibição em dois modos: bytes para exibição e bytes de comandos de configuração. Esses modos são definidos pelo próprio MK para um pino de exibição específico (D / C). Uma lista completa de comandos é fornecida na folha de dados no visor. Alguns desses comandos são usados no meu dispositivo e são usados para inicializar a exibição quando a energia é aplicada ao dispositivo: coeficiente de temperatura, contraste, modo de desenho seqüencial (horizontal ou vertical) etc. Percebo imediatamente que o modo de desenho horizontal é aplicado. Isso significa que, ao transferir um byte no modo de exibição, o endereço aumenta automaticamente uma linha por linha à direita. Quando a linha termina, o endereço da posição vai para o início da próxima linha. Basta enviar primeiro um comando de posicionamento especial para o display para um endereço específico de linha e coluna (posição inicial) e depois enviar bytes de dados sequencialmente um após o outro para exibir gráficos. Vale ressaltar a característica do espaço de endereço e a interpretação dos gráficos, dependendo dos bytes recebidos pelo display. Observo que, para gráficos monocromáticos, um byte contém informações sobre oito pixels de uma vez.
A exibição em questão é dividida verticalmente em 6 zonas horizontais com 8 linhas cada (6 * 8 = 48). Cada coluna de cada zona corresponderá a um byte específico, que é enviado com o endereço da coluna correspondente (0 ... 83) e o número da zona (0 ... 5). O endereço não é contado de um, a partir do zero. Por exemplo, se você se posicionar no endereço (34; 2) e enviar um byte de dados 255 (no formato binário “11111111”), todos os 8 pixels acenderão de 16 a 23 na vertical e na 35a coluna na horizontal. Na minha opinião, uma das desvantagens segue esse recurso: a incapacidade de controlar o estado de cada pixel individualmente no nível do hardware. Um byte é o menor pedaço de dados para gráficos. Quando um byte é transmitido para o endereço atual, todos os 8 pixels correspondentes na zona atual são atualizados. O monitor não suporta a leitura das informações gráficas atualmente exibidas no microcontrolador. Portanto, se necessário, é necessário armazenar as informações de saída em um buffer dedicado antecipadamente e alterar o estado de qualquer pixel (bits), aplicar máscaras de bits aos bytes desse buffer e transferi-las para a tela novamente.
Modelagem e reflexão sobre a localização de uma informação gráfica específica na tela foram realizadas levando em consideração os recursos acima. Isso foi feito para simplificar o código ao escrever o programa. E não é por acaso que o tamanho da fonte foi considerado da categoria 8, 16, 24, ou seja, um múltiplo de 8. Também dividi as informações gráficas, por analogia com a exibição, em 6 zonas horizontais. Na primeira zona, os valores absolutos e atuais (a partir do momento em que o dispositivo é ligado) são exibidos em letras pequenas. Na segunda zona, os valores absolutos e atuais do caminho (em quilômetros com arredondamentos para centésimos). Na terceira zona - velocidade média. Na quarta - velocidade máxima e em letras grandes - a velocidade atual. Na quinta zona, duas barras de progresso são exibidas para indicar que a ROM está cheia e o número de substituições. Na sexta, última zona, a data e a hora. É a quinta zona que é a exceção quando na direção vertical de qualquer coluna tomada há pixels relacionados a informações diferentes. Portanto, essas informações usando máscaras de bits são coletadas em um buffer, cujo conteúdo é exibido nessa quinta zona. Além disso, em 3-5 zonas, há informações para desenhar um quadro em torno do valor de velocidade exibido. Na última zona, cada primeiro bit (menos significativo) em todas as colunas é definido como "1" para desenhar a linha separadora (40ª linha). Para esta simulação e visualização de endereços, descrevi tudo isso nas células do Excel.

É assim que a primeira janela de exibição se parece. Apenas duas janelas. A segunda janela é a saída do gráfico (histograma) do movimento. Para isso, são atribuídas 5 zonas (40 linhas) verticalmente e todas as 84 colunas horizontalmente. A sexta zona com o relógio é a mesma para as duas janelas.
Ao programar, decidi não recorrer ao uso de nenhuma biblioteca para trabalhar com essa exibição. Pessoalmente, é mais fácil entender a folha de dados, implementar parte das funções pessoalmente do que entender a biblioteca. Além disso, certas vantagens foram encontradas nisso. Recentemente, depois de baixar uma das bibliotecas, descobri suas características funcionais. É universal, com sua ajuda, você pode controlar os pixels individualmente e se posicionar no endereço real do pixel. Mas a biblioteca usa um buffer de 84 * 6 bytes de tamanho e esse buffer de timer é enviado periodicamente para a exibição, atualizando os gráficos. Assim, o temporizador e parte da memória MK estão ocupados. No meu caso particular, não há necessidade de usar uma biblioteca, pois ao modelar, tomei o cuidado de maximizar a separação de informações entre as zonas exibidas, que estão em total conformidade com as zonas de exibição. E não há necessidade de atualizar periodicamente as informações no visor: as informações são atualizadas somente se e somente quando forem alteradas (a cada rotação da roda, a cada pressionamento de um botão, etc.). Assim, enfatizo mais uma vez: dependendo da tarefa, você pode evitar o uso de qualquer biblioteca.
Para trabalhar com um microcircuito de clock e ROM, também não recorri ao uso de bibliotecas: todas as funções são bastante simples e implementadas por mim depois de estudar as folhas de dados para esses componentes.
Agora considere o circuito elétrico do dispositivo.

O layout do velocímetro é relativamente simples. Além de tudo isso, o circuito contém um elemento IC5 MAX756, que serve como um conversor de energia de 3 a 5 Volts para uma fonte de alimentação confiável da bateria original do telefone celular Nokia 3310. Eu não implementei o circuito para a fonte de alimentação de 3 volts devido à falta de MK e periféricos adequados. No momento, ainda não adquiri o MAX756, e todo o circuito ainda é alimentado por uma bateria externa da Krona usando o regulador LM7805 (não é a melhor opção). Ele se conecta ao fone de ouvido na parte inferior do telefone. O interruptor reed SF1, que é um sensor de rotação da roda, é conectado à porta de interrupção INT0 MK (pino 32). Ele se conecta com segurança da parte inferior do telefone à porta de carregamento. Os botões funcionais S1-S3 conectados aos botões "1", "2", "3" do telefone móvel estão conectados a portas arbitrárias (pinos 23, 27, 28). Um pino S4 está conectado ao pino 29 da redefinição do MK, que coincide com o botão superior para ligar o telefone móvel. Eu fiz assim. O dispositivo em si não tem um modo de espera e liga com energia. Um monitor IC2 e um conector para piscar X1 estão conectados à porta SPI do controlador (pinos 15-17). Com o conector, que eu queria criar com base nos “spots” existentes na placa-mãe original para parear com um PC (no mesmo lugar), fiquei com um pequeno problema e, no futuro, vou transferi-lo para outro lugar. Uma interface UART para conexão do usuário a um computador é conectada ao mesmo conector, através do qual a data e a hora no dispositivo estão configuradas (pinos 30 a 31, RX / TX). O monitor é conectado ao controlador através de divisores nos resistores, que servem para reduzir a tensão, porque o monitor funciona com uma tensão de 3,3 V. Além disso, os pinos do monitor D / C (dados / comando), SCE (strobe) e RES (redefinição do display) são conectados a portas arbitrárias MK PB0, PB1 e PB2, respectivamente (pinos 12-14). O display é alimentado pelos diodos D1-D3 e resistor R6, que servem para reduzir a tensão de 5 para 3,3 V, evitando o uso de um regulador linear. O Cr1 de quartzo com clock de MK com um valor nominal de 4,5 MHz foi escolhido aleatoriamente, mas deliberadamente. Ele caiu no meu braço e eu decidi usá-lo. Os transistores Q1 e Q2 são conectados às portas do PD4 e PD5 MK (pinos 2 e 9), nas quais os LEDs da luz de fundo da tela e do teclado são carregados. O controlador fornece a capacidade de controlar as luzes de fundo individualmente, como o layout original do telefone celular (isso foi no nível do hardware e não no nível do usuário), embora na prática isso não seja necessário. O barramento I2C é conectado às portas PC2-PC3 (pinos 25-26) e, por simplicidade, é implementado programaticamente usando a biblioteca apropriada (embora esteja conectado às portas TWI do hardware). A ROM do IC3 e o IC4 do relógio em tempo real (RTC) estão suspensos no barramento. Faça imediatamente uma reserva para que não haja críticas nos comentários: eu sei que o DS1307 não é a melhor solução, mas no momento do desenvolvimento do circuito eu não sabia da existência do DS3231. A ROM está localizada em um conector removível, semelhante a um cartão SIM. Uma porta adicional do controlador PC1 (pino 24) é usada para receber pulsos com uma frequência de 1 Hz com RTC, pela qual o tempo no visor é atualizado. Todos os componentes do kit de corpo passivo - de acordo com as fichas técnicas de cada componente ativo.
Considere considerações matemáticas para calcular certos parâmetros. Como já mencionado no início, o princípio da medição da velocidade baseia-se no cálculo do período de rotação da roda e a distância é calculada com base na medição do número dessas rotações. O controlador mede o tempo entre o pulso anterior e o recebido do interruptor reed. O resultado da medição é convertido em um valor de velocidade, dividindo o valor do perímetro da roda pelo período de revolução, e esse valor é atualizado no visor a cada pulso (rotação da roda). Vale a pena notar aqui que, do ponto de vista da física, é calculada a velocidade média de uma bicicleta em uma seção do caminho correspondente ao perímetro da roda. Separadamente, o número de pulsos é calculado e convertido em um valor de distância. Para medir o período de rotação da roda, o controlador usa seu próprio temporizador. O ATmega8 possui um temporizador de 8 e 16 bits. A faixa dinâmica da medição depende da profundidade de bits do temporizador. No meu caso, é usado um timer de 16 bits, pois 8 bits (256 contagens) são categoricamente insuficientes. O período máximo de medição (antes do temporizador exceder) corresponderá à velocidade mínima medida. Você pode inserir o chamado timer de software, que medirá grandes períodos. No entanto, para simplificar o programa, eu não fiz isso. Com o quartzo usado de 4,5 MHz e um valor máximo de divisor de 1024 na configuração do temporizador, temos: (1 / (4500000/1024)) = 0,000227556 seg. Este valor corresponde ao período mínimo da conta. E o período máximo da conta será 0,000227556 * 65536 = 14,913 segundos. A velocidade máxima mensurável correspondente ao período mínimo mensurável será de cerca de 30.000 km / h. Não valia a pena estipular, a “reserva de cima” é simplesmente enorme.
Mas a velocidade mínima medida correspondente ao período máximo medido será 2,26 / 14,913 / 1000 * 3600 = 0,54 km / h. Aqui 2,26 é o perímetro da roda da bicicleta (em metros) no meu caso. Estou muito feliz com este valor mínimo medido. Se a bicicleta se mover a uma velocidade inferior a 0,54 km / h, o velocímetro registrará a falta de movimento (e o excesso de temporizador). Com essa interface UART de quartzo de 4,5 MHz, funciona bem a uma velocidade de 2400 bauds, com um erro aceitável aceitável. Essa velocidade também é suficiente, principalmente porque eu uso o UART para configurações de relógio único de um computador (para copiar a data e a hora de um computador para um dispositivo). Se você elevar o quartzo em frequência mais alta, a velocidade mínima mensurável aumentará, o que será inaceitável para mim,e você precisará usar um cronômetro de software. E se você analisar abaixo, o desempenho do dispositivo como um todo diminui. Por isso, decidi deixar esse quartzo em particular.Observo que os valores de período e velocidade são inversamente proporcionais, e o temporizador do microcontrolador mede o período discretamente. No nosso caso, a faixa de medição (0,000227556 ... 14,913) é igualmente marcada com pontos no valor de 65535, dividindo-a em muitos intervalos iguais. E esses pontos correspondem a todos os tipos de valores medidos. Usando a conversão de intervalos de tempos em velocidade, esse sistema de intervalos é convertido de uniforme para inversamente proporcional. Portanto, a faixa de velocidades medidas de maneira diversa é dividida em intervalos irregulares. A duração desses intervalos aumenta com o aumento do próprio valor da velocidade. Diante desse fato, a enorme "reserva de cima", sobre a qual escrevi um pouco mais, não ficará errada. Na prática, será suficiente levar o valor de 100 km / h para a velocidade máxima medida da bicicleta.Isso é apenas para não introduzir um novo dígito (centenas) e não aumentar a largura do parâmetro exibido no visor. Calculamos que a duração do intervalo entre valores possíveis adjacentes a uma velocidade na vizinhança é igual a, por exemplo, 90 km / h. Usando as fórmulas inversas ou a seleção, é fácil calcular que, para o valor do timer 397 (de 65536 possível), a velocidade medida corresponde a 90,06 km / h. E com um valor de temporizador vizinho de 398 - 89,83 km / h. E a diferença entre as velocidades é de 0,23 km / h, o que já é mais do que aceitável. E em velocidades mais baixas, essa diferença será ainda menor. O visor mostra o valor da velocidade para o centésimo mais próximo. No entanto, na prática, arredondar para o todo mais próximo ou para o décimo é geralmente suficiente. Do exposto, podemos concluir: a não uniformidade da “grade” de velocidades pode ser negligenciada,uma vez que o erro de medição causado por ele não excede o erro permitido.Para calcular a distância, basta multiplicar o número de pulsos (revoluções) pelo perímetro da roda. Nesse caso, é claro, a distância é calculada com precisão no perímetro da roda, o que é bastante aceitável. A velocidade média atual é calculada como a razão entre a distância atual percorrida e o valor do tempo a partir do momento em que foi ligada. Este é o tempo que o controlador considera contando o número de pulsos que chegam uma vez por segundo com o RTC. A velocidade média na tela é atualizada junto com a atualização da hora (uma vez por segundo). Todos os outros parâmetros são atualizados a cada rotação da roda.Agora, sobre os pequenos recursos da interface. O primeiro botão é usado para alternar entre os modos (modo gráfico ou modo de exibição de valor). O segundo botão - para exibir a velocidade máxima absoluta (para todos os tempos), em vez da relativa, quando pressionada. Além disso, a data e a hora de atingir essa velocidade são exibidas no lugar da data e hora atuais. E também, o valor do endereço ROM atual é exibido no lugar do valor da velocidade relativa (para controle). Este valor pode ser estimado pela barra de progresso horizontal na 38ª linha do visor. Nesta ROM, com uma capacidade de 65536 bytes (512 kbit), os parâmetros medidos são registrados. Como será dito mais adiante, basta registrar o parâmetro medido inicialmente (o período de rotação da roda) com uma marca do tempo inicial.Todos os outros parâmetros são facilmente calculados por um programa de computador no estágio de verificação da ROM. O terceiro botão é usado para controlar a luz de fundo. Diferentemente do esboço da tela acima, depois removi zeros insignificantes nos parâmetros secundários para exibi-los mais claramente. No modo gráfico, um histograma da velocidade do movimento é desenhado da esquerda para a direita, o que demonstra claramente o processo de mudança de velocidade em uma pequena parte da distância de 84 rotações da roda. O valor do histograma é a velocidade na escala de 1 pixel por 1 km / h. Se a velocidade exceder 40 km / h, a imagem é reduzida verticalmente em 2 vezes, para evitar a queda de escala. Recursos completos do comportamento do dispositivo não precisam ser descritos aqui.Mais tarde, removi zeros insignificantes nos parâmetros secundários para exibi-los mais claramente. No modo gráfico, um histograma da velocidade do movimento é desenhado da esquerda para a direita, o que demonstra claramente o processo de mudança de velocidade em uma pequena parte da distância de 84 rotações da roda. O valor do histograma é a velocidade na escala de 1 pixel por 1 km / h. Se a velocidade exceder 40 km / h, a imagem é reduzida verticalmente em 2 vezes, para evitar a queda de escala. Recursos completos do comportamento do dispositivo não precisam ser descritos aqui.Mais tarde, removi zeros insignificantes nos parâmetros secundários para exibi-los mais claramente. No modo gráfico, um histograma da velocidade do movimento é desenhado da esquerda para a direita, o que demonstra claramente o processo de mudança de velocidade em uma pequena parte da distância de 84 rotações da roda. O valor do histograma é a velocidade na escala de 1 pixel por 1 km / h. Se a velocidade exceder 40 km / h, a imagem é reduzida verticalmente em 2 vezes, para evitar a queda de escala. Recursos completos do comportamento do dispositivo não precisam ser descritos aqui.O valor do histograma é a velocidade na escala de 1 pixel por 1 km / h. Se a velocidade exceder 40 km / h, a imagem é reduzida verticalmente em 2 vezes, para evitar a queda de escala. Recursos completos do comportamento do dispositivo não precisam ser descritos aqui.O valor do histograma é a velocidade na escala de 1 pixel por 1 km / h. Se a velocidade exceder 40 km / h, a imagem é reduzida verticalmente em 2 vezes, para evitar a queda de escala. Recursos completos do comportamento do dispositivo não precisam ser descritos aqui.Vale a pena notar uma das diferenças características entre o meu velocímetro e o barato adquirido. Consiste na velocidade de atualização da indicação de velocidade no visor. No meu dispositivo, ele é atualizado imediatamente, conforme calculado, a cada rotação da roda. Nos dispositivos adquiridos, é atualizado com um certo atraso. Talvez esse atraso seja devido a uma tentativa de filtrar o ruído de medição (por exemplo, usando o método da média móvel) para estabilizar a velocidade exibida no visor para uma clareza mais detalhada. Ou talvez a exibição seja atualizada completamente a intervalos regulares (por exemplo, duas vezes por segundo). Pode ser conveniente, mas eu queria implementar uma atualização de velocidade a cada revolução do volante.A placa de circuito impresso é feita pelo método LUT na forma da placa de circuito original do telefone celular usado. Na fabricação da placa de circuito, usei o programa SLayout. Ao mesmo tempo, tirei uma foto da placa original em ambos os lados do scanner e coloquei as imagens no SLayout como modelo. Isso é necessário para desenhar blocos para conectar a tela, botões e conectores em locais exclusivamente necessários. Na fabricação do cartão, ocorreu um erro de cerca de 0,5 mm. Esse erro acabou sendo aceitável em termos de combinação de elementos e almofadas. No entanto, esse erro afetou a qualidade da luz de fundo: os LEDs selados foram deslocados em uma fração de milímetros e não caíram no foco de mandris de dispersão de luz. Por esse motivo, o brilho da luz de fundo diminuiu, reduzindo a eficiência.As figuras abaixo mostram uma vista da placa de circuito no SLayout, juntamente com três pequenas placas de circuito impresso para ROM na forma de um cartão SIM. Além disso, são mostradas digitalizações da placa de circuito impresso original dos dois lados.
Alguns elementos (botões, conectores) são interconectados por jumpers de fio fino por falta de capacidade de colocar faixas. Existe uma margem para todos os botões disponíveis, ou seja, é possível usar qualquer botão disponível. Pode ser conveniente tornar o botão grande no centro um botão para alternar os modos de exibição. No canto superior esquerdo da placa, há uma bateria de 3 volts RTC. Em geral, todos os elementos no quadro são colocados corretamente, com a coordenação de suas dimensões com as dimensões do gabinete. Ao contrário do original dourado, a placa interna é revestida com solda comum. Como mostra a prática inicial, o contato com a tela e outros periféricos não é perdido.O programa para MK acabou sendo bastante grande e ocupa uma parte significativa de sua memória. Além disso, o programa prevê o uso de sua própria memória não volátil do controlador (EEPROM) para gravar e salvar as informações necessárias. A tabela abaixo mostra a distribuição dessas informações pelos endereços EEPROM.Morada | Tamanho | Dados |
0 0 | 4 | n (para S) |
4 | 2 | t_min (para v_max) |
6 | 6 | Data de t_min |
12 | 2 | Endereço EEPROM |
14 | 1 | Contagem de EWPROM RW |
128 | 80 | Dígitos 8X8 |
208 | 30 | Dígitos 3X5 |
Os primeiros quatro bytes armazenam a distância percorrida como o número de rotações da roda. Escolhi especificamente o tipo inteiro de 32 bits para essa variável, pois, na prática, os valores do caminho percorrido são relativamente grandes. Por exemplo, uma variável inteira de 16 bits pode economizar um máximo de 65.536 rotações (cerca de 148 km), o que é naturalmente pequeno. Dois bytes seguem para manter a velocidade máxima absoluta. De fato, o tempo mínimo de rotação da roda é economizado. A variável ocupa dois bytes, porque seu valor é o resultado da medição de um timer de 16 bits. Os próximos 6 bytes são a data e hora em que a velocidade máxima acima foi atingida. Os dados são apresentados exatamente no formato em que são lidos no chip RTC (excluindo o dia da semana). Em seguida, dois bytes que armazenam o valor do endereço atual da ROM externa. Esse é um tipo de ponteiro, necessário para a possibilidade de continuar a gravação de estatísticas na ROM após a próxima ligação do dispositivo. O MK deve saber em que posição do espaço de endereço da ROM externa parou pela última vez. A partir desta posição, o MK continuará a gravar. Esse valor é alocado em 2 bytes, já que o espaço de endereço da ROM externa é de 16 bits. Isto segue um tamanho de ROM de 64 kB. A seguir, é uma variável de byte único que armazena o valor do número de substituições de ROM. A substituição é o caso quando o ponteiro acima atinge o valor máximo e passa a zero. Nesse caso, as informações recém-recebidas na ROM começarão a ser gravadas desde o início, apagando as informações antigas disponíveis nela. Uma variável inteira de byte único é capaz de armazenar um máximo de 256 valores. Lembro que os valores do ponteiro de endereço da ROM e o número de substituições são visualmente indicados por duas barras de progresso no visor. Além disso, após um grande espaço de backup do EEPROM MK, iniciando no endereço 128, as informações gráficas sobre os dígitos 8x8 são armazenadas. Para isso, 80 bytes são alocados (8 bytes para cada dígito, conforme mencionado anteriormente). E, finalmente, começando no endereço 208, 30 bytes são armazenados para obter informações gráficas sobre pequenos dígitos 3x5 (três bytes por dígito).
Além do programa principal do microcontrolador, escrevi mais três programas auxiliares para o computador, que serão discutidos abaixo. Todos os programas não possuem uma interface gráfica e funcionam na linha de comando do Windows XP.
O primeiro programa permite copiar a data e a hora de um computador para o velocímetro da bicicleta através da porta COM. O velocímetro da bicicleta está conectado ao computador através do chip MAX232. Usando o WinAPI, o programa recebe a data e hora atuais em uma variável estrutural especial do tipo SYSTEMTIME. O dia, mês, ano, número do dia da semana, horas, minutos, segundos no formato decimal são extraídos dessa variável. Todos esses números, com exceção do ano, não excedem duas casas decimais (menos de 100) e ficam dentro de um byte. O valor do ano é convertido em um número de dois dígitos, subtraindo dele o número 2000, o valor do milênio atual. Cada um desses números decimais de dois dígitos é convertido para a característica de formato decimal binário do chip RTC. Nesse formato, um número de dois dígitos também ocupa um volume de um byte. Os 4 bits mais significativos são codificados no dígito das dezenas e o menos significativo - o número de unidades. Posteriormente, uma parcela de 13 bytes é formada a partir desses números, de acordo com um protocolo que eu determinei anteriormente. Os cinco primeiros bytes representam a palavra "TIME =" de acordo com a codificação ASCII padrão. Depois siga segundos, minutos, horas, dia da semana, dia, mês, ano. O último byte é o caractere "#", como o caractere do final da mensagem. Este pacote é enviado do computador para o dispositivo através da porta COM. O programa de microcontrolador recebe o pacote e verifica se está correto, de acordo com o formato acima. Se os cinco primeiros bytes forem “TIME =” e o último for “#”, o envio será considerado correto e os bytes internos serão interpretados na ordem correspondente. Sem alterar essa sequência de bytes, o controlador envia para o chip RTC via barramento I2C, configurando-o para a data e hora atuais. Observo que este microcircuito suporta o cálculo dos dias da semana de 1 a 7, embora, como um calendário que determine a correspondência da data e dia da semana, não seja. Não forneci informações sobre o dia da semana no meu dispositivo.
O segundo programa foi projetado para processar dados do conteúdo de uma ROM externa. Inicialmente, assumiu-se que esse conteúdo deveria ser copiado da ROM para o arquivo de imagem usando algum programa conhecido que funciona com programadores conhecidos de MK e ROM (por exemplo, “icprog”). No entanto, tendo estudado o princípio da operação I2C com mais detalhes, consegui implementar essa funcionalidade e incluí-la no meu programa. O esquema do programador ROM desta série, que usei no dispositivo, é apresentado na figura abaixo.

A ROM está conectada à porta COM do computador, que não é usada como meio de troca de informações via RS-232 (onde é suficiente usar as saídas TX, RX, GND), mas como meio de entrada e saída arbitrária de sinais lógicos. Através do terminal TX, a ROM é alimentada, que é estabilizada em até 5V pelo regulador 78L05. Ao controlar a saída TX do computador, podemos ativar ou desativar o chip ROM. A linha de relógio unidirecional do SCL está concentrada no pino RTS da porta COM e a linha de dados bidirecional SDA está concentrada em dois pinos: CTS (recepção de dados) e DTR (transmissão de dados). Resistores e diodos zener D1 e D2 são usados para limitar o nível de sinal para TTL, no qual a ROM trabalha.
Fiz este programador padrão para o meu caso especial, onde, em vez de um soquete para ROM, é usado um leitor SIM de um telefone celular quebrado.

Por meio do WinAPI, o programa acessa os pinos da porta COM do computador, define os valores necessários para eles (0 ou 1) e também remove o valor binário de entrada da ROM do pino CTS. Com base neste kit de ferramentas, a funcionalidade I2C foi implementada de acordo com a especificação relevante, sobre a qual não entrarei em detalhes. O programa pode ler o conteúdo da ROM em uma imagem de arquivo (como um programador regular) e também processar um arquivo ou processar informações diretamente da ROM. O processamento de informações consiste em obter os arquivos estatísticos de saída em um formato tabular predeterminado, com base nas informações de entrada da ROM. Cada arquivo corresponde a uma viagem (do momento da corrente até a próxima vez que o dispositivo é ligado). Primeiro, descreverei brevemente o formato de entrada que defini com antecedência. Cada vez que o dispositivo é ligado, dois bytes de zeros são gravados no endereço atual, que é lido na EEPROM do microcontrolador. Quando a roda começa a girar (no primeiro impulso) após um tempo limite ou após ligar o dispositivo, a data e a hora atuais são gravadas no formato decimal binário (como é armazenado nos registros do chip RTC). E então dois bytes de "unidades" 0xFF são gravados. Durante a rotação da roda, para cada k-ésimo pulso (k = 2,3, ...), o tempo de rotação da roda entre o (k-1) e o k-ésimo pulso é registrado por dois bytes (alto e baixo). Obviamente, essas informações são suficientes para vincular a distância atual (não absoluta) percorrida e a velocidade até a data e hora. O formato de saída é texto e é uma tabela tabular nos arquivos * .csv que são abertos no Excel clicando duas vezes no mouse. As linhas nesta tabela correspondem às rotações das rodas e os valores da coluna são mostrados abaixo.
ADR | Valor do Endereço ROM |
DATA / HORA | Data e hora de início |
Dez | Valor do temporizador decimal |
tempo | Hora atual |
t | Tempo de viagem desde a inicialização |
v | Velocidade |
n | Velocidade |
S | O caminho |
um | O número absoluto de rotações (apenas dentro da ROM atual) |
aS | Caminho absoluto (apenas dentro da ROM atual) |
n_dia | O número de rotações para o dia atual |
Dia | O caminho para o dia atual |
v_max | Velocidade máxima para a viagem atual |
av_max | Velocidade máxima absoluta (apenas dentro da ROM atual) |
v_mid | Velocidade média para a viagem atual |
Uma captura de tela do conteúdo desse arquivo no Excel é mostrada na figura abaixo. Além disso, são mostrados gráficos de alterações na velocidade atual, média e máxima em várias cores em um sistema de coordenadas. Argumento (eixo X) - valores de velocidade como dados de entrada. A figura mostra as alterações de parâmetro para as primeiras 730 rotações. A distância percorrida está associada a essa dependência linear variável (730 rotações corresponde a aproximadamente 1650 m). Portanto, podemos dizer que os gráficos refletem a dependência das velocidades na distância (precisa para a escala horizontal), em contraste com a dependência tradicional da velocidade no tempo, à qual devemos prestar atenção. Como já mencionado, esse recurso se deve à ideologia e ao princípio da medição da velocidade pela velocidade da roda. Afinal, um determinado momento é atribuído a cada rotação da roda (o momento da aproximação do ímã e do interruptor reed). Naturalmente, essa sequência de carimbos de data e hora não é uniforme. No entanto, por formalidade e conveniência, o Excel tem a capacidade de especificar uma matriz de valores de tempo no caminho ou hora atual como argumento para gráficos. Mesmo assim, deve-se lembrar que a real dependência da velocidade no tempo (em intervalos uniformes para o caso discreto) teria parecido diferente, com uma escala horizontal variável.


A figura abaixo mostra a mesma dependência de velocidade em rotações, mas já está usando o filtro usando o método da média móvel com uma largura de janela de 11 rotações. Todos os gráficos são criados no Excel usando métodos conhecidos.

Comparando os dois gráficos da mudança de velocidade, é óbvio que o componente de alta frequência está ausente no gráfico filtrado, ou seja, ruído removido. A largura da janela média móvel de 11 revoluções (cerca de 25 m), na minha opinião, é muito grande. Se você realmente levanta a questão de filtrar as leituras do ruído, basta uma pequena largura da janela, por exemplo, igual a três. Esse algoritmo pode ser incorporado ao programa velocímetro da bicicleta, porque pode ser usado não apenas para analisar as leituras, mas também para exibir essas leituras em tempo real. Apesar da simplicidade desse algoritmo, não entrarei nos detalhes de sua descrição, pois esse tópico é abordado no curso de matemática e está além do escopo deste artigo. E aqui está outro esclarecimento sobre a velocidade média. Como já escrevi, a velocidade média é o único parâmetro que não é atualizado a cada rotação da roda, mas a cada segundo. Fiz isso para garantir que a tela mostre uma alteração na velocidade média, mesmo com movimentos muito lentos. Portanto, os valores das leituras exibidas no visor em tempo real diferem ligeiramente dos valores calculados no futuro pelo programa de computador no estágio de verificação da ROM. As leituras da velocidade absoluta, caminho absoluto e velocidade máxima absoluta também serão diferentes. O visor mostra valores realmente absolutos (durante toda a vida útil do dispositivo) e nas tabelas de saída - apenas dentro dos limites da ROM atual que está sendo lida.
O terceiro programa, em essência, é o mesmo programa para o microcontrolador de firmware. Eu trabalho com o programador STK 200 mais simples conectado à porta LPT do computador, ou melhor, com seu analógico, se você pode chamar assim, porque no caso mais simples o programador não contém nenhum elemento ativo. De fato, o MK através da interface SPI se conecta diretamente a pinos específicos da porta LPT e funciona como escravo. O programa implementa um protocolo para troca de dados com o controlador ATmega8 de acordo com a folha de dados (p. 237). A camada física do SPI é implementada gerenciando os registros da porta LPT usando a conhecida biblioteca dinâmica "inpout32.dll". Minha biblioteca não está conectada como um projeto (desde que evitei criar um projeto como tal no “Dev-cpp” criando um “arquivo” simples), mas usando a função LoadLibrary usando o tipo estrutural HINSTANCE. A biblioteca "inpout32.dll" é mapeada para uma variável desse tipo e, posteriormente, os ponteiros para as funções dessa biblioteca são extraídos em variáveis separadas. Inpout32.dll possui apenas duas funções que são responsáveis pela entrada e saída de dados. Essas funções são acessadas usando ponteiros pré-extraídos. Os pinos da porta LPT são controlados individualmente usando máscaras de bits. No meu caso particular, o programa que escrevi trabalha com a área EEPROM do controlador e foi projetado para ler, reservar, gravar, corrigir e restaurar a partir de uma cópia de backup dos dados armazenados nele que eu pintei anteriormente. Como todos os outros programas, o programa é executado na linha de comando. Nesses casos, para implementar a multifuncionalidade do programa, são utilizadas as funções “caso de comutação” e uma caixa de diálogo de texto, por exemplo, “digite '1' para a operação nº 1, ..., digite '0' para sair do programa”. Os dados são exibidos em vários formatos convenientes para mim. Além do acima, o programa pode exibir um despejo completo do controlador EEPROM em 512 bytes na tela. Além disso, o programa pode gravar informações gráficas sobre as fontes usadas na memória do controlador. No caso de letras pequenas, tamanho 3X5, o programa obtém informações do arquivo de texto "Fontes 3X5.txt", localizado no mesmo diretório. O arquivo contém uma tabela tabular de 30 bytes (3 por 10) gravada no formato hexadecimal. Se desejado, ele pode ser facilmente editado em um editor de texto, alterando os gráficos dessa fonte. Como já mencionado, essas letras pequenas são tão simples que alterar seus gráficos não faz sentido. A única coisa é que seu deslocamento vertical pode ser necessário apenas, pois existe um estoque de espaço na altura de 8 pixels e a fonte tem uma altura igual a 5. No caso de uma fonte grande, tamanho 8X8, que exibe a velocidade atual, forneci a funcionalidade muito mais interessante. As informações gráficas sobre essa fonte são apresentadas não em um arquivo de texto como uma tabela de bytes, mas em arquivos BMP visuais gráficos. Cada dígito corresponde a um desses arquivos. Seus parâmetros são tamanho 8X8, monocromático com uma paleta de preto e branco. Abaixo está uma captura de tela do conhecido editor gráfico "MS Paint" com o arquivo "8.bmp" aberto.

Empiricamente, estudei a estrutura dos arquivos BMP monocromáticos obtidos no MS Paint ”e, com base nisso, pude aprender a ler todos os pixels de uma imagem BMP monocromática (excluindo o uso de estruturas e bibliotecas auxiliares). Na fase de leitura horizontal linha a linha de baixo para cima (é assim que a estrutura do arquivo BMP é organizada), o programa converte as informações no formato vertical específico para a exibição usada. Esta operação é realizada em uma única passagem, na qual máscaras de bits e acúmulo de valores variáveis são usados. Abaixo, mostrarei esta seção de código para o i-ésimo dígito, prestando atenção à simplicidade do processo.
for(k=0; k<8; k++){ fnt[i][k] = 0; } for(j=0; j<8; j++){ fseek(f, 62+4*j, SEEK_SET); byte = ~fgetc(f); for(k=0; k<8; k++){ if(byte & pow2(7-k)){ fnt[i][k] += pow2(7-j); } } }
No primeiro loop, os elementos da matriz fnt são inicializados em zeros. Além disso, cada k-ésimo elemento dessa matriz (k = 0 ... 7) para o i-ésimo dígito (i = 0 ... 9) carregará informações gráficas sobre cada coluna correspondente de cada dígito correspondente. O próximo ciclo é a execução ao longo das linhas da imagem do arquivo BMP. Com o operador fseek, nos posicionamos bytes no deslocamento 62 + 4 * j do arquivo BMP predefinido f. A especificidade da fórmula pela qual o deslocamento é calculado dependendo do número da linha j é determinada pela estrutura do arquivo BMP. Na variável intermediária de bytes, obtemos o valor de bytes no deslocamento acima. Esse byte armazena informações sobre todos os oito pixels de uma imagem monocromática na linha atual j. O operador '~' executa uma inversão bit a bit do byte, o que leva a uma inversão de cores de cada pixel. Isso se deve ao fato de um pixel preto na paleta de um arquivo BMP monocromático corresponder a um "0" lógico e branco - "1". Na exibição aplicada, pelo contrário. Em um loop aninhado, ocorre uma análise de bytes do byte e, ao mesmo tempo, as informações são acumuladas na matriz de saída fnt. Função pow2 - elevando dois para um número inteiro não negativo, escrito independentemente. Em vez desta função, você pode usar o operador de deslocamento bit a bit mais eficiente “<<”, mas no momento em que escrevi este programa eu não o estava usando.
Além disso, o programa fornece a capacidade de gravar na memória do MK uma das várias opções gráficas para essa fonte de minha escolha. Essas opções são implementadas usando diretórios (pastas) com um nome no formato “v1”, “v2”, “v3” etc., que estão localizados na pasta “Fonts 8X8” no mesmo diretório do programa. E já nessas pastas estão os arquivos BMP necessários. Graças à funcionalidade acima, é possível corrigir ou desenhar números de uma "folha em branco" em um editor gráfico, salvando e distribuindo-os entre diretórios. Eu tenho três opções de fonte. A primeira opção é o original. O segundo - como o original, mas com um zero riscado e uma unidade modificada (sem sublinhado). A terceira é uma fonte com uma borda retangular.
As fotos abaixo mostram: a placa de circuito fabricada do dispositivo na parte de trás; um dispositivo na mesa com energia conectada a ele (com uma versão não final do firmware); um dispositivo em operação montado em uma bicicleta com um gráfico das mudanças de velocidade exibidas.



No processo de operação do dispositivo, no entanto, pequenas falhas foram identificadas associadas aos recursos de fabricação. Antes de tudo - mau contato da tela com as almofadas da placa de circuito impresso. No celular original, os contatos no quadro são banhados a ouro e não há oxidação. No meu caso, eles são simplesmente enlatados.
Com base no exposto, decidiu-se refazer o dispositivo em outro caso, bem como refazer a placa de circuito impresso, na qual a tela será soldada insolentemente. Comecei esse processo recentemente. O resultado é um design mais robusto.



Defendi o dispositivo a partir de um pedaço de acrílico, com 17 mm de espessura, em uma fresadora CNC. Para fazer isso, eu esboçei preliminarmente os esboços do caso no programa SPlan, quase completamente sem saber o assunto dos desenhos, CAD, etc.

Esses esboços são necessários para a apresentação geral e a obtenção das coordenadas dos pontos de controle. Com base neles, é elaborado um programa para a máquina CNC, levando em consideração os princípios gerais e seqüências de fresamento. Escrevi o programa CNC manualmente no Excel, usando as funções de preenchimento automático para operações repetidas.


Também corrigi levemente o layout do dispositivo, que é apresentado na figura abaixo.

Em vez da retroiluminação já desnecessária do teclado, há um LED de beleza que pisca a cada volta do volante. Os conectores também são redesenhados e não há outros elementos que não eram necessários na versão atualizada do design. Além disso, encontrei e instalei o quartzo 4.433619 MHz, corrigindo levemente algumas constantes no código-fonte do meu próprio programa. Também foram feitas algumas pequenas alterações no programa.
Uma fotografia do produto final é apresentada abaixo. O dispositivo é alimentado por uma bateria que fica a bordo da bicicleta. A partir disso, a iluminação também é fornecida para viagens no escuro.

Foi nesse design que o dispositivo funcionou completamente sem falhas. A única desvantagem é o uso de um chip RTC de qualidade não muito alta: no inverno a baixas temperaturas, o tempo é notavelmente rápido, é necessário ajustá-lo uma vez por mês.