Engenharia de Presentes



Do lado de fora da janela chove, o calendário é dezembro. A hora das férias está se aproximando e, portanto, a hora dos presentes. O colega Pavel quer um novo laptop para si e a namorada Masha quer uma casa à beira-mar. E, apesar do salário digno da profissão de tyzhprogrammer, não vivemos em um mundo de infinitas possibilidades, o que significa que não posso dar a essas pessoas exatamente o que elas mais querem (mesmo que Pasha possa ser meu melhor Pavel, a quem Eu sei, mas Masha está bem).

É aqui que o problema de "presentes baratos" aparece. Não dá para dar um presente caro a todos, mas não quero dar outra caixa de chocolates, uma vela ou uma figura indistinta. Então, você precisa combinar negócios com prazer - gosto de fazer as coisas com minhas próprias mãos, e o resultado é ótimo como presente. Esta é uma história sobre como mais uma vez fingi ser engenheiro e fiz vários presentes à mão.

Uma pequena digressão do tópico principal


Não posso ir imediatamente ao tópico principal, então vou começar de longe. Alguns anos atrás, o jogo "The Witcher 3" foi lançado. Meu amigo me aconselhou a jogar e, em geral, eu realmente admirava o jogo. Decidi o que fazer e lhe dei algo temático relacionado ao jogo ... Não vou me aprofundar na descrição do jogo (o Google ajudará a todos) ou dizer que não me ocorreu muita coisa pelas palavras-chave "The Witcher, Engineer, Gift".

O personagem principal do jogo tem um cavalo chamado "Roach" (na dublagem russa), o herói de tempos em tempos a leva com a frase "Move, Roach". Eu decidi fazer um brinquedo mecânico sobre o tema "mexendo baratas".

Naturalmente, o presente foi concebido como algo completamente inútil, estúpido, mas engraçado, então o plano era o seguinte:

  1. Há uma caixa que oculta o mecanismo em si.
  2. O mecanismo é um eixo, girando o qual o cavalo está se movendo.
  3. A máxima "tenacidade" do movimento do cavalo é bem-vinda. Inicialmente, pensou-se que o cavalo deveria se mover como um peixe, e não como um cavalo (afinal, barata), mas o resultado foi "algo intermediário".
  4. Tudo isso será feito a partir de compensado, que de acordo com os desenhos pode ser cortado com precisão a pedido com um laser.

A principal desvantagem da escolha do material e o fato de que o corte será feito por encomenda foi o fato de eu ter perdido a oportunidade de criar um protótipo, o que significa que todos os problemas de mãos tortas e o não cumprimento da regra da “medida dos sete tempos” se fizeram sentir rapidamente:



Embora, no final, o fato de muitos detalhes do mecanismo de folga devido a folgas muito grandes ajudaram a compensar o fato de eu ter conectado as peças e o eixo de maneira bastante torta. Aqui, como se costuma dizer, “menos menos dá mais” e o mecanismo como um todo funcionou, como pretendido:



Depois, havia apenas uma pequena pintura e o resultado foi uma caixa:



Então alguém dirá que foi necessário tornar a caixa transparente para que fosse possível observar o trabalho do interior, mas, na verdade, eu imaginei que não poderia montar todo o mecanismo e a caixa tão limpos e ordenadamente por dentro que não machucariam. olhe através das paredes transparentes da caixa. Portanto, uma caixa opaca é uma medida necessária.

Resta apenas empacotá-lo, amarrar um laço em uma caixa e o presente está pronto:



Mas para não incomodar a criança interior, que queria se sentir como um engenheiro em uma situação em que colei duas peças de madeira compensada, decidi fazer um “desenho”. Perdoe-me todos aqueles que entendem alguma coisa nos desenhos técnicos, porque Entendo que isso é mais uma paródia do desenho do que um desenho real, mas, como me pareceu, ele agregou valor a um simples brinquedo:



Hoje eu ...


Às vezes, o destino brinca conosco e de alguma forma sugere que algo deve acontecer em breve. A história de um dos meus dispositivos começa exatamente da mesma maneira. Encomendei alguns eletrônicos pequenos no valor de US $ 5, que, como de costume, passaram um mês na estrada, após o qual recebi um SMS informando que o pacote estava me esperando na estação de correios local. A caixa acabou sendo muito maior do que eu esperava e imediatamente levantou dúvidas sobre seu conteúdo. Dúvidas foram confirmadas - por dentro, além das pequenas coisas que pedi, havia também uma tela de tinta colorida em três cores com uma diagonal de 4,2 polegadas. Entrei em contato com o vendedor, ele confirmou que tinha estragado alguma coisa ao fazer as malas, mas disse que posso considerar isso um presente e usá-lo como achar melhor.

O destino sugeriu para mim que chegou a hora de iniciar um novo projeto e esse projeto será algo com uma exibição de tinta eletrônica. Depois de me familiarizar brevemente com as especificações do dispositivo e conectar o monitor ao controlador, certifiquei-me de que as especificações não me mentissem sobre o tempo de atualização. A tela foi atualizada por mais de 10 segundos, piscando e tentando me causar um ataque epilético:


(Eu não tenho fotos antigas de conexão da tela, então aqui o dispositivo já tem uma aparência mais significativa)

Ficou claro que você precisa de um dispositivo simples que não exija animações complexas (e animações em geral). E então me deparei com um calendário de humor:


O calendário de humor é um conjunto de fotos simples e assinaturas irônicas para eles. Decidi criar um calendário (que na verdade não é um calendário) com o nome "Hoje eu" ... Será um dispositivo simples que todos os dias exibe uma imagem que caracteriza o "estado de espírito" hoje e uma descrição dele. Além disso, o calendário também pode ter outras funções, mas o calendário principal seria precisamente o "calendário" - sua própria imagem para cada dia.

O módulo de papel eletrônico permitiu exibir três cores (preto, vermelho e branco), que devem ser transmitidas ao módulo, como duas figuras - preto e branco e vermelho e branco. De fato, seria mais correto dizer que a tela simplesmente espera um bitmap monocromático, em que cada bit determina a cor de um pixel (não tenho certeza de que esse termo seja aplicável ao papel eletrônico, mas espero que a ideia seja clara). Um bitmap separado pode ser definido para o canal preto ou vermelho. Portanto, há um conjunto de bytes em que cada bit definido como 1 corresponderá a um pixel colorido e todos os bits que permanecerem 0 serão pixels brancos na tela. A resolução da tela é de 400 x 300 pixels, ou seja, para uma imagem em preto e branco, serão necessários 15.000 bytes (8 pixels são codificados em um byte). Para as três cores, serão necessários 30.000 bytes, se você não tentar compactar a imagem de maneira mais compacta. Do ponto de vista da implementação, os criadores da tela poderiam simplesmente selecionar dois bits por pixel e armazenar o estado real das coisas (onde é vermelho, onde é preto e onde é branco), mas isso exigiria os mesmos 30.000 bytes, mas mesmo para imagens monocromáticas exigiria a transferência de 30.000 bytes.

Como em qualquer um dos meus outros trabalhos manuais, comecei a inventar tarefas para mim, para que tudo não se transformasse em "conectar a fiação e fazer o download da biblioteca". Mesmo se levarmos em conta a capacidade de implementar algum tipo de algoritmo de compactação de imagem no lado do controlador, ficou claro que, sem um armazenamento externo para arquivos de imagem, o controlador ficaria muito deprimido. Foi decidido pegar um cartão SD e escrever um invólucro de código simples para trabalhar com o FAT32. Obviamente, seria possível ficar sem um sistema de arquivos e gravar dados diretamente em um cartão de memória, mas me pareceu menos conveniente para adicionar novos arquivos, e foi interessante para mim implementar as operações básicas para trabalhar com o FAT32 com minhas próprias mãos.

É importante esclarecer que eu tenho o hábito de escrever coisas sozinho (você não deve me dizer que há um mar de bibliotecas, eu sei sobre isso e com o Google) quando faço essas coisas, mas desde Antes disso, eu não tinha o prazer de trabalhar com o FAT32 em um nível baixo, era um processo bastante divertido.

Não entrarei em detalhes sobre como trabalhar com o FAT32 e o cartão SD como um todo, pois a Internet está cheia de artigos sobre esse tópico (e não quero transformar minha história em uma recontagem de especificações), mas falarei sobre algumas coisas que precisavam ser implementadas. É necessário implementar não apenas as funções de leitura e gravação de um arquivo (decidi armazenar algumas configurações e estados no mesmo cartão SD, e não na EEPROM), mas também as funções de procurar um arquivo no sistema de arquivos, se você precisar trabalhar com da maneira usual.

Todos os dados no cartão de memória são divididos em clusters (a principal unidade endereçável no sistema de arquivos FAT32) e os clusters já estão divididos em setores. Para ler o arquivo "habr.txt" do cartão SD no FAT32, você precisa:

  1. Inicialize o cartão de memória.
  2. Leia o setor no endereço zero e verifique se o sistema de arquivos FAT32 possui um determinado cabeçalho (você pode pular esta etapa se acreditarmos na sorte).
  3. Leia o setor no endereço zero e obtenha "Logical Block Addressing" (LBA).
  4. Leia o setor no endereço recebido (LBA) e obtenha os dados necessários (qual cluster é a raiz - o diretório raiz, quantos setores estão no cluster etc.).
  5. Leia o cluster "Diretório Raiz" (na verdade, a leitura é feita por setores, você só precisa ler quantos setores houver setores no cluster) pelo número. Possui sua própria fórmula para converter números de série do cluster em endereços físicos. As informações do arquivo são armazenadas aqui, então lemos os dados em busca do arquivo desejado. Há mais um pouco sobre nomes de arquivos: o nome pode ser curto ou longo, dependendo disso, os dados são armazenados em um único local (na mesma estrutura) ou em um registro adicional, que também deve ser lido separadamente. Quando um arquivo com o nome desejado é encontrado, obtemos o cluster no qual está localizado o início (ou talvez o arquivo inteiro, se ele se encaixar no tamanho do cluster), bem como o tamanho do arquivo. Se o arquivo não for encontrado neste cluster, procuraremos o próximo cluster e repetiremos o processo de pesquisa de arquivos.
  6. Leia o cluster no endereço encontrado. E continue a ler mais os clusters e procure o próximo cluster até que todos os dados tenham sido lidos.

Parece-me que é mais fácil dizer o princípio do sistema de arquivos àqueles que implementaram listas vinculadas pelo menos uma vez, porque de fato, o sistema de arquivos FAT32 é um conjunto de blocos de dados e um tipo de tabela que indica onde procurar o próximo bloco de dados. Ler todos os dados do FAT32 é um processo em que lemos os dados, procuramos o endereço do próximo bloco, lemos os dados, procuramos o endereço do próximo bloco, etc.

Não implementei todos os cenários possíveis e simplifiquei algumas coisas:

  • Todos os arquivos estão na raiz do cartão de memória e a navegação no diretório não é usada.
  • Todos os arquivos têm nomes abreviados.
  • O controlador na inicialização lê uma lista de arquivos e os armazena na memória para não procurar cada arquivo novamente.
  • O número máximo de arquivos é limitado por uma constante (e, de fato, desenhei apenas algumas dezenas de imagens).

Resumindo, tudo isso é um motivo convincente para obter uma biblioteca pronta e não gastar muito tempo lendo a documentação, desenvolvendo e depurando. Eu me aconselharia a implementar essas coisas apenas para fins educacionais ou "por diversão".

A tela também impôs algumas limitações, como qualquer imagem nela é exibida desta maneira:

  1. Acordamos e inicializamos a tela (para prolongar sua vida útil e economizar energia, a tela basicamente dorme).
  2. Nós expomos o canal necessário (por exemplo, preto).
  3. Encaminhamos 15000 bytes da imagem.
  4. Nós expomos o canal necessário (por exemplo, vermelho).
  5. Encaminhamos 15000 bytes da imagem.
  6. Dizemos ao visor para extrair dados do buffer.
  7. Esperamos até que a tela termine de desenhar.
  8. Dizemos à tela para dormir.

Para imagens monocromáticas, você pode pular as etapas 4 e 5. Para uma imagem em três cores, a ordem de transmissão das imagens em preto e branco e vermelho e branco não é importante, porque o vermelho é sempre pintado sobre preto, o preto somente sobre branco e apenas os pixels permanecem brancos, que são brancos e pretos e brancos e vermelhos e brancos.

Por uma questão de simplicidade (para não aumentar o número total de arquivos), decidi armazenar as imagens em preto e branco e vermelho e branco como um único arquivo, onde a imagem em preto e branco é imediatamente seguida por vermelho e branco:



O resultado da comparação dessas imagens foi algo assim (parece-me que cada um de nós pelo menos uma vez na vida se sentiu como um cervo com chifres - uma perna):



De fato, as duas imagens foram seguidas por outra imagem que continha uma descrição do estado (clicando no botão, você pode obter uma descrição que corresponda à imagem exibida hoje).

Devido à memória limitada do controlador, os dados do cartão de memória nunca são lidos inteiramente na memória do controlador. A imagem do cartão de memória é lida em fragmentos determinados pelo tamanho do setor (por simplicidade, assumimos que esse tamanho é sempre estático e não pode ser alterado de cartão para cartão) e cai no processo de processamento de dados do cartão. Na minha implementação, a função de ler um arquivo toma como entrada o número do cluster, o tamanho do arquivo e o retorno de chamada a serem "extraídos" para cada setor lido. Essa abordagem nos permitiu usar várias funções diferentes de processamento de arquivos para ler e exibir a própria imagem ou sua descrição.

Portanto, a seguinte lógica recaiu na função de retorno de chamada da leitura de imagens de um cartão de memória:

  1. Defina o canal necessário (o canal é determinado aleatoriamente) antes de enviar dados para o visor.
  2. Acompanhe os dados transmitidos para mudar de canal quando o envio de dados para o canal anterior for concluído.
  3. Envie dados recebidos do cartão.
  4. Determine que os dados necessários foram transmitidos e que o restante dos dados (imagem com descrição) pode ser ignorado.

Foi complicado pelo fato de eu ter decidido inserir imagens que continham mais dados do que deveriam ser exibidos na tela. I.e. há alguma imagem, que é o plano de fundo e é sempre estática e corresponde ao tamanho da tela, e há uma imagem muito maior na qual é necessário tirar uma área aleatória (o tamanho da tela) e exibir.

Essa imagem impunha requisitos adicionais ao manipulador - era necessário calcular quantos bytes da linha atual da tela foram transferidos, quanto mais precisava ser adicionado na próxima chamada (se a linha cair na borda do tamanho do setor) e quantos deveriam ser ignorados.

Visualmente, essa situação pode ser mostrada assim:



Há um certo buffer no qual existe uma “janela” do tamanho necessário (seção verde) e você só precisa ler os dados dessa janela, lendo os dados do buffer em fragmentos de N bytes. Seria possível visualizar um processo de leitura como este:



Em geral, adicionar a lógica de trabalhar com a tela a uma função que sempre recebe um buffer de 512 bytes e qual deve determinar qual desses 512 bytes é necessário (se é necessário algo) não se revelou uma tarefa tão fácil de resolver. "Na testa". Mais precisamente, a tarefa não era tão complicada quanto não-padrão em comparação com as soluções cotidianas; portanto, surpreendentemente, foi muito interessante resolvê-la. Para mim, era como uma “tarefa das olimpíadas”, onde era necessário calcular a quantidade de eletricidade necessária para contrair os músculos, a fim de transferir a água de um balde para outro com duas colheres (uma colher em cada mão).

Para entender melhor qual é a dificuldade, adicionarei outra animação aqui, apenas "em termos de" o conteúdo do cluster e não o arquivo inteiro (todas as outras informações precisam ser armazenadas separadamente):



Conforme planejado, o calendário deve mostrar uma nova imagem todos os dias, ou seja, ele deve poder monitorar a hora (mesmo quando desligada), o que significa que também é necessário um módulo de relógio em tempo real (RTC). E, apesar do fato de o meu controlador possuir um relógio em tempo real, é quase impossível comprar uma bateria para ele, porque os contatos não estão conectados ao quadro. Decidi não estuprar as pernas do controlador na tentativa de soldá-las e peguei o RTC chinês externo. Trabalhar com o RTC era para ser completamente simples:

  • Quando ligado, obtenha tempo no RTC chinês.
  • Defina a hora no RTC interno.
  • Use o RTC interno para contar o tempo e esquecer os chineses até o próximo desligamento.

Mas aqui, tudo acabou não sendo tão simples, porque o RTC interno do controlador funciona com o tempo no formato usual (carimbo de data e hora do UNIX), e seu amigo chinês usa Decimal Codificado em Binário (BCD). Antes disso, não encontrei esse formato e fiquei muito surpreso que mesmo os módulos modernos do Arduino o usassem. A essência do formato é bastante simples - há um byte que, por exemplo, armazena o número de segundos. Os quatro bits de alta ordem armazenam dezenas e as quatro bits de baixa ordem armazenam unidades. Acontece que a representação hexadecimal desse byte em si contém um tempo legível - o byte 0x49 corresponde a um valor de 49 segundos (embora no sistema decimal, esse byte corresponda a 72).

Pelo que entendi, isso aconteceu tão historicamente que era mais fácil usar o RTC diretamente com codificadores de tela para criar um relógio, mas tive que converter o carimbo de data / hora do BDC em UNIX com canetas.

Além da tela, do módulo de relógio em tempo real, do cartão de memória e do sistema de arquivos, era necessário envolver todas essas glândulas em um estojo, que também precisava ser fabricado, ou seja, "Draw". Você pode ler com mais detalhes toda a dor que encontrei na minha última publicação; tudo era exatamente o mesmo aqui:


(Eu não planejei a produção em massa, todos os detalhes são resultado de medições incorretas ou de soluções mal pensadas)

Como resultado, o caso e os detalhes necessários foram desenhados (não há capa na imagem):



Os botões foram colocados em uma peça separada para facilitar a montagem (parece que eu ainda aprendi alguma coisa desde a época do último projeto):



A montagem (com exceção das capas frontal e traseira) o dispositivo fica assim: O



monitor é anexado ao estojo com gravatas. Isso acabou sendo um método muito mais conveniente do que aparafusá-lo.

Bem, um pequeno inferno para os perfeccionistas (uma barba de fios e componentes):



A montagem acabou sendo um dispositivo para o qual eu fiz um pequeno livro - instruções:



A tampa traseira é parafusada, o que permite desmontar o dispositivo se for necessária uma violência adicional por dentro:



Sim, é mais fácil comprar uma casa à beira-mar!


E então alguém que leu até este ponto dirá: “E isso é uma alternativa aos presentes simples ?! Sim, você imediatamente precisa investir 100500 horas do seu tempo, o que é muito mais caro que o dinheiro! ” Não discutirei sobre esse tópico, apenas direi que para mim é um processo meditativo e mato dois coelhos com uma cajadada - por um lado, faço coisas que basicamente ninguém precisa (poucos me pagariam para desenvolver algo tal), mas que são interessantes para eu fazer, e uma pessoa recebe um objeto único como presente, que, embora não carregue uma carga útil óbvia, dá um sorriso.

No entanto, para que não haja sabor residual de soluções que exijam muito tempo, compartilharei mais algumas histórias curtas.

Agora, em geral, ficou muito na moda imprimir coisas em uma impressora 3D. Os dispositivos de impressão tornaram-se muito mais acessíveis, e o software para criar modelos é simples o suficiente para as crianças entenderem.

Clame por ajuda


No trabalho, tivemos uma piada sobre o fato de que, se você precisar de ajuda, basta gritar a gaivota e alguém definitivamente o ajudará. Na verdade, eu não sei com o que isso está relacionado e de onde veio essa piada, mas em correspondências internas imagens de gaivotas frequentemente começaram a aparecer, sugerindo que alguém precisa de ajuda.

No entanto, o escritório de tipo aberto e a modéstia interna de alguns colegas não lhes permitiram aproveitar ao máximo a oportunidade de pedir ajuda como essa. Então, um "homem não-engenheiro" decidiu vir em socorro, levando um "MP3 Player Module para MP3 para o Arduino", um clone chinês do Arduino Nano, alguns fios e alguns mp3s com a gravação dos sons das gaivotas.

Em geral, deve-se observar aqui que eu tenho o hábito de pedir vários módulos com desconto, o que, parece-me, pode um dia ser útil, ou recebo eletrônicos como um presente de amigos / conhecidos que não acharam esses eletrônicos úteis. Portanto, a palavra "por aí" não é acidental, mas descreve com muita precisão o estado das coisas.

Como sou uma pessoa longe da modelagem 3D, peguei um modelo pronto da cabeça da gaivota e fiz as alterações necessárias. Ou seja, a partir das mudanças era necessário:

  1. Separe o bico da cabeça para imprimi-lo em uma cor diferente.
  2. Faça uma “cavidade” na qual todos os eletrônicos estarão (alto-falante, tocador, arduino e fios).

O resultado é algo assim (o bico é dividido em duas partes para melhor qualidade de impressão):



não acho que faça sentido falar sobre o código, porque além de inicializar o player, havia apenas um manipulador de cliques de botão e tocando uma das gravações de voz de gaivota (em geral: playSound (rand () & 3);).

Depois disso, deixe a gaivota para imprimir e coletar tudo juntos. Como resultado, temos um "simulador de chá" completo (a cor da gaivota é determinada pelo plástico disponível), que se conecta ao USB e quando você clica no botão na cabeça da gaivota, ele reproduz o "pedido de ajuda":



Ainda mais fácil?


Uma colega reclamou que ela estava constantemente distraída enquanto escrevia testes. Encontramos na Internet um modelo 3D de óculos e fazemos pequenas alterações:



Como resultado, temos óculos - cortinas. Não nos distraímos e outros entendem que você não deve se distrair:



Muito simples!


Então, para criar você precisa:

  1. A capacidade de encontrar ou desenhar uma muleta no editor de vetores.
  2. A capacidade de desenhar 2 cilindros no editor 3D, um a mais que o outro em ~ 0,4 mm.
  3. A capacidade de fazer um simples pedaço de papel - uma etiqueta.
  4. Impressora 3D (serviço de impressão próprio ou personalizado).
  5. A impressora é comum.

E agora, em ordem ... Desenhamos uma muleta:



Desenhamos dois cilindros:



Imprimimos as peças e a etiqueta e recebemos um presente excelente e simples de "tyzhprogramistov":



Para que foi tudo isso?


“Às vezes o destino brinca conosco e de alguma forma sugere que algo deve acontecer em breve.” Várias vezes na minha vida eu tinha idéias que queria realizar, mas esperei por algo. Eu não faria um "calendário" eletrônico se uma tela gratuita não viesse da China, isso significa que eu nem lidaria com o FAT32, não aprenderia sobre o formato BCD usado no RTC.

Talvez alguém leia essa história (ou pelo menos veja as figuras) e pense: “Droga, se ele pudesse, então eu posso fazê-lo ainda melhor!” E, como resultado, trará alegria a alguém próximo.

Do lado de fora da janela está chovendo, dezembro está no calendário. A hora das férias está se aproximando e, portanto, a hora dos presentes. Faça e receba presentes interessantes, não apenas mais uma caixa de chocolates, uma vela ou uma estatueta.

Source: https://habr.com/ru/post/pt480792/


All Articles