Misturador de cores CMYK com ESP32 DIY

Vou tentar ser breve ao explicar o conceito, mas suspeito que será uma surpresa interessante para diversas pessoas o que disporei sobre cores. Pensei em fazer o misturador de cores CMYK com ESP32 usando bombas peristálticas devido à precisão que elas têm. Junto a um sensor de cores, certamente seria um projeto (no mínimo) divertido.

Quero salientar também que fiquei elaborando esse projeto na cabeça por dias. Tentei tirá-lo da mente, mas cada vez que digladiava com minha intuição, mais concreta a ideia se tornava; foram dias meditando, vários outros dias programando pouco a pouco, totalizando um número de horas de dedicação altíssimo para poder entregar esse projeto ao público do blog. Ainda teve a revisão de texto pelo Ricardo Amaral, cujo tempo dedicado também deve ser valorizado. Feitas as considerações, por favor, não deixe de compartilhar o artigo em suas redes sociais, inscreva-se e clique no sininho para receber notificações em nosso canal Dobitaobytebrasil no Youtube.

Já adianto que apesar de ter trabalhado com outdoors e ter sido cartunista de um jornal razoavelmente grande, não sou especialista nem em cores luz, nem em cores pigmento, mas acredito que o conteúdo prévio é, no mínimo, interessante.

Diferença do RGB e CMYK

Comecemos pelo RGB, da qual estamos mais habituados em tecnologia; e seja paciente, o misturador de cores tem muitos conceitos.

Cores RGB e profundidade de cores

O RGB que todos estamos habituados (e que já faz parte de nossas vidas talvez tanto quanto o CMYK) é a composição de cores através da mistura de espectros de luz em diferentes frequências. RGB significa Red, Green e Blue, as cores luz primárias. Quando misturadas em sua intensidade máxima, resulta em branco. Chegou a fazer na escola o disco de Newton?

disco de newton

No disco estão dispostas as cores que, ao ser girado velozmente, formam o branco. Por que branco, e não preto? – respondo.

Quando olhamos para uma cor, o que vemos é o reflexo da frequência de luz não absorvida pelo objeto. Quando giramos o disco, nossos olhos passam a não reagir em tempo de perceber mais as variações, e a soma de todas as frequências de luz resultam no branco. É parecido com o efeito de persistência de visão, quando multiplexamos um display de 7 segmentos.

O RGB é utilizado para exibir cores em monitores, displays de celulares, televisores e outros que não me ocorrem no momento. Normalmente temos 24 bits de “profundidade de cores”, que seria a terceira potência de um Byte, ou 256^3 = 16.777.216 cores. Isso porque 1 Byte vai de 0 à 255, sendo 0 desligado e 255 a intensidade máxima. A mistura de cores luz é diferente da mistura de cores pigmento, como explicado a seguir.

Cores CMYK

Antes de adentrarmos tecnicamente no âmago do projeto do misturador de cores, temos que ter um entendimento mínimo dos padrões de cores.

O CMYK é a combinação de cores pigmentos primárias, sendo o Cyan, Magenta, Yellow e blacK (mas na verdade o ‘K’ é de ‘Key’). Apesar de hoje ser comumente identificado com black, o K pode ser outro pigmento, como marrom ou azul. Agora talvez seja a parte mais interessante relacionada às cores pigmento. As cores que vemos em objetos não são suas cores, mas sim o reflexo das frequências de luz cujo objeto não absorve. Quando vemos preto, significa que o material está absorvendo praticamente todas as frequências de luz. Quando vemos branco, significa que o material está refletindo praticamente todas as frequências de luz.

Na impressão, um recurso utilizado para atingir uma ampla gama de cores é chamado halftoning (ou “screening”), formado por padrões contendo pontos de cores distribuídos em determinadas proporções para gerar tonalidades.

Veja essa pequena imagem:

exemlo de halftoning

Um outdoor de estrada normalmente tem 150 pontos por polegada. Quando visto à distância, a “imperfeição” quase nunca é notada. Quando fazemos banners ou cartazes, utilizamos uma resolução de 300 pontos por polegada, já que eles serão vistos de perto. Portanto, o halftoning é fundamental para produção gráfica de grandes formatos, o que também ajuda a economizar tinta.

Agora, a mesma imagem em tamanho maior, como se estivesse sendo vista mais de perto:

exemplo de half toning

Sem o halftoning só seria possível obter as 3 cores primárias (vermelho, azul e amarelo), as 3 cores secundárias (verde, laranja e roxo), o marrom (a mistura das 3 cores primárias) e, dependendo da intensidade da mistura, o preto. Nosso misturador de cores trabalhará basicamente com as misturas citadas e as variações de tonalidade dessa gama.

Outra técnica utilizada é chamada de “padrão moiré”, que é mais uma forma de produzir tonalidades. Amplie a imagem a seguir e repare que ela é composta por linhas paralelas em diferentes direções, sem cruzamentos.

exemplo de moiré

Da mesma forma, serve para “misturar” cores e obter referências fora do gamut através da mistura visual, não apenas para gradação de tonalidade.

Há mais uma curiosidade no padrão de impressão, que utiliza diferentes ângulos para cada uma das cores. Variando a granularidade, usando halftoning e moiré, aliados aos ângulos de impressão, podemos obter uma vastidão de cores em impressão gráfica, mas lembre-se: o misturador de cores simplesmente mistura as tintas para obter uma cor. E essa limitação é do misturador de cores? Vejamos.

Apesar de todos os recursos citados, ainda assim há uma limitação relacionada à impressora, na qual a gama de cores dentro de uma “paleta” chamada “gamut” contempla as cores imprimíveis. Daí entram os padrões que não podem ser obtidos com o CMYK, como a paleta Pantone, que é um formato proprietário e utiliza “hexachrome” (CMYKOG – “O” de “Orange”, “G” de “Green”) e que foi descontinuado em 2008, quando a Adobe deixou de suportar o plugin HexWare. Tem também o padrão CcMmYK, que melhora significativamente impressão de pele, com a inclusão de ciano mais claro e magenta mais claro, permitindo inserção extra de pontos para aumentar a combinação, ao custo de maior utilização de tinta. Enfim, dá para escrever livros sobre o assunto sem sequer se aprofundar nele.

Aqui está uma imagem CMYK de 1902, composta no último quadro por cada um dos fotolitos que a precede.

fotolitos CMYK

Mistura de cores RGB vs CMYK

Desde a pré-escola aprendemos a misturar cores primárias para obter cores secundárias ou terciárias; vermelho e azul resulta em roxo nas cores pigmento, enquanto nas cores luz o vermelho e azul resultam em rosa. Vermelho e verde em CMYK resultam em marrom, enquanto em RGB resultam em amarelo.

Basicamente devemos pensar que: cores luz são referentes à energia irradiada em uma frequência de luz, enquanto as cores pigmentos representam a energia que não é absorvida pelo material – a tinta, o giz, a caneta etc. Observando esse último parágrafo, cito algo que para muitos será uma revelação, mas é só para título de curiosidade: a cor não está na matéria; o que acontece é a reflexão de frequências de luz não absorvidas pelo material exposto à luz. Quando vemos um objeto vermelho, significa que ele absorveu as demais frequências de luz e refletiu o vermelho. Quando uma tinta é manipulada, seu preparo é feito com os pigmentos que refletem o espectro de luz desejada.

Como converter RGB para CMYK

Não é difícil fazer uma conversão satisfatória, mas existem muitas considerações a respeito. Essa conversão depende do meio, como por exemplo: impressoras, scanners, máquinas fotográficas digitais – ou, o nosso misturador de cores. Por essa razão, uma calibragem é quase sempre necessária, podendo talvez ser dispensada em experimentações.

Até mesmo para impressoras, a tinta não tem um padrão absoluto em toda a série de cartuchos. Se for recarregado então; hummm! Desse modo, existem métodos técnicos, científicos e empíricos para determinar uma conversão.

Aqui escrevi uma função para converter RGB para CMYK, usado em nosso misturador de cores:

void rgb2cmyk(uint8_t R, uint8_t G, uint8_t B){
  float Rfrac = (float)R/(float)255;
  float Gfrac = (float)G/(float)255;
  float Bfrac = (float)B/(float)255;

  float K = 1-max({Rfrac,Gfrac,Bfrac});

  float C = (1-Rfrac-K)/(1-K);
  float M = (1-Gfrac-K)/(1-K);
  float Y = (1-Bfrac-K)/(1-K);

  
  sleep(3);
  Serial.println("RGB");
  Serial.println(Rfrac);
  Serial.println(Gfrac);
  Serial.println(Bfrac);

  Serial.println("CMYK (%)");
  Serial.println(C);
  Serial.println(M);
  Serial.println(Y);
  Serial.println(K);
}

A lógica é baseada na seguinte fórmula:

Referência: https://www.rapidtables.com/convert/color/rgb-to-cmyk.html

Conversão de RGB 24 bits para CMYK:
os valores R,G,B são divididos por 255 para modificar a faixa de 0..255 to 0..1 (um mapeamento):
R' = R/255
G' = G/255
B' = B/255

A cor chave preta (K) é calculada a partir das cores vermelho (R'), verde (G') e azul (B'):
K = 1-max(R', G', B')

A cor azul (C) é calculada a partir das cores vermelho (R') e preto (K):
C = (1-R'-K) / (1-K)

A cor magenta (M) é calculada a partir das cores verde (G') e preto (K):
M = (1-G'-K) / (1-K)

A cor amarela (Y) é calculada a partir da cor azul (B') e preto (K):
Y = (1-B'-K) / (1-K)

No Arduino o resultado deve ser um pouco pior que no ESP32, pela perda de precisão. Como vamos misturar todos os pigmentos, estamos limitados às cores citadas anteriormente, com alguma variação de tonalidade.

Como exemplo de teste da função, fiz a chamada assim:

rgb2cmyk(255,30,20);

E o resultado exibido na serial foi:

saída de teste do misturador de cores

Houve uma pequena perda nessa conversão, mas não deve ser significativa para o projeto proposto, que pode ser um misturador de anilina para misturar ao glacê, de modo a conseguir criar um padrão de cores, por exemplo. Isso pode ser ótimo, principalmente quando pode ser necessário repetir a cor para, digamos, um bolo confeitado com as cores de uma personagem infantil.

Repare que o valor devolvido em CMYK é em porcentagem. De cara já dá um susto; como pode 92% + 88%? – Calma.

Primeira coisa importante a considerar é que podemos obter o preto em RGB com diversos parâmetros diferentes em CMYK no misturador de cores, e isso pode variar. Não é necessário que todos os elementos de CMYK estejam em 100% para obter o preto. Do mesmo modo, um cinza (que em RGB é moleza, basta definir as 3 cores com o mesmo valor) pode ter (e terá) variações, normalmente acentuando o ciano.

Como o Ricardo Amaral questionou, acabei decidindo incluir essa observação: você pode ter tons de cinza em RGB colocando as 3 cores com o mesmo valor, exceto 0 e 255, que seria “preto” (desligado) e branco.

Vou aproveitar também a observação do Vinícius da Robocore e comentar brevemente sobre as cores “HTML”, que é a representação RGB em hexadecimal; 1 byte tem 8 bits, indo de 0 à 255. Essa representação em hexadecimal seria 0x00 à 0xFF. Logo, um vermelho máximo em RGB representado em hexadecimal seria “#FF0000“. Voltemos ao CMYK.

Não podemos considerar precisão na conversão por diversas razões, sendo uma delas a seleção de uma cor fora do gamut, significando que não é uma cor imprimível em CMYK. De qualquer modo, a cor que tirarmos poderá ser um padrão definitivo, desde que usando os mesmos pigmentos.

A mistura será feita com as 4 cores, considerando o branco à parte (já que o branco exigiria uma quinta bomba e nem sempre é necessário tê-lo na mistura, principalmente porque se considera branco o papel). A limitação de cores na mistura é realmente considerável. Uma forma de reduzir o preto é acrescer 3 em cada cor (CMY) para cada subtração de 5 do preto (K), o que poderia auxiliar a aumentar o brilho da cor. Mas já viu que aí vai tinta, hein? Isso é possível para valores acima de 3% de CMY, desde que eles não estejam muito próximos a 0, senão haverá também impacto na cor pretendida.

Para facilitar o entendimento da mistura, estas são as combinações:

mistura CMYK

As porcentagens do CMYK se referem à quantidade de ejeção baseado no volume de branco. Tirando por base 10ml de branco para cada cor, teremos no exemplo de saída mostrado anteriormente:

  • 0ml de ciano.
  • 8,8ml de vermelho.
  • 9,2ml de amarelo.
  • 0ml de preto.

E nesse caso, para ficar mais escuro teríamos que adicionar 3% em CMY, mas o ciano passará a influenciar a tonalidade pretendida. Outra coisa que está clara é que a luminosidade da amostra 255,30,20 não será aplicada à anilina:

cor salmão

Ficou meio salmão no monitor do notebook e no monitor conectado ao HDMI ficou mais alaranjado. Isso me fez lembrar outro fator importante de quando eu usava Photoshop; calibrar o monitor para ter uma correspondência com o que será impresso é uma opção que me deixa bastante confortável. Só que isso eu fazia em idos dos anos 90 em monitores CRT, então vou pular essa parte dessa vez e ver qual será o resultado verdadeiro.

Como converter CMYK para RGB

Por qual razão converter CMYK para RGB nesse projeto? Bem, a resposta é simples.

Como existe a possibilidade de ajuste de cor pelo display, é necessário ter uma referência mínima para saber o que está sendo feito. Então, adicionei uma barra entra os medidores, que exibe a cor correspondente ao arranjo CMYK, que é atualizado em tempo real. Como o display só é capaz de exibir cores luz, converter um valor selecionado a partir do CMYK é fundamental. Mas não é tão simples assim também.

No computador utilizamos o RGB888, ou RGB 24bits (que é a soma dos 3 bytes). O display não tem essa profundidade de cores, ele tem apenas 16bits, sendo um display RGB565. Isso significa que temos 5 bits para R, 6 bits para G e 5 bits para B. Para fazer a proporcionalização “manual” não seria uma tarefa simples nem agradável, já que o foco é o projeto em si. Mas a biblioteca TFT_eSPI é incrível e tem uma função que converte RGB888 para RGB565. Desse modo, bastou fazer a conversão do CMYK para RGB888 e passar o resultado para a função da biblioteca, atribuindo então a cor resultante ao retângulo entre os meters. Simples!

Para fazer as coisas bem isoladas e funções genéricas, criei uma função exclusiva de conversão CMYK para RGB:

void cmyk2rgb(uint8_t C, uint8_t M, uint8_t Y, uint8_t K){
    /*
    A reversa também é simples e será utilizada para manipular o CMYK direto no display.
    O RGB é inteiro, mas o CMYK precisa ser passado de 0 à 1 novamente. No artigo tem uma
    imagem de exemplo do cálculo na calculadora, mas segue um exemplo:
    C = 43
    M = 30
    Y = 10
    K = 10

    R = 255 * (1-(43/100))*(1-(10/100)) = 130,815 ; arredondar para cima quando > 0.5

    ==================================
    Os valores R,G,B são dados em faixa de 0..255.

    A cor vermelha (R) é calculada a partir do ciano (C) e preto (K):
    R = 255 × (1-C) × (1-K)

    A cor verde (G) é calculada a partir do magenta (M) e preto (K):
    G = 255 × (1-M) × (1-K)

    A cor azul (B) é calculada a partir do amarelo (Y) e preto (K):
    B = 255 × (1-Y) × (1-K)
    */
    memset(RGBarray,0,sizeof(RGBarray));
    RGBarray[0] = round(RGB_MAX * (ONE_DOT-((float)C/HUNDRED)) * (ONE_DOT-((float)K/HUNDRED)));
    RGBarray[1] = round(RGB_MAX * (ONE_DOT-((float)M/HUNDRED)) * (ONE_DOT-((float)K/HUNDRED)));
    RGBarray[2] = round(RGB_MAX * (ONE_DOT-((float)Y/HUNDRED)) * (ONE_DOT-((float)K/HUNDRED)));
}

A variável uint8_t RGBarray[3] é uma variável global. Os valores são lidos e aplicados a partir de outra função – a plotPointer. Ao final dela, foi adicionada a linha contendo o posicionamento e a cor a ser aplicada no retângulo:

tft.fillRect(5, 130, 230, 20, tft.color565(RGBarray[0],RGBarray[1],RGBarray[2]));

A interface foi incrementada um pouco mais após isso. O picker será um dispositivo externo fazendo comunicação por socket TCP. Em relação à interface, achei uma boa ideia adicionar o IP para identificar o dispositivo, ainda que em modo access point; ainda mais em modo station. Como a interface já está com a distribuição preenchida, optei por plotar o IP sobre a barra da amostra de cores, que adicionei entre o meter analógico e os lineares.

Uma task dedicada a receber e tratar a comunicação de rede foi criada, de modo a rodar assincronamente. Ao receber dados válidos na comunicação, as variáveis de cor são atualizadas, então automaticamente a interface do misturador de cores ajusta as cores e valores para ter um feedback visual. Por segurança, o processo só pode ser iniciado pelo botão Iniciar na interface, evitando assim que o processo seja disparado pela rede. Quando o processo de mistura é iniciado, outra proteção garante que não haja atualização das variáveis nesse momento, para não interferir na mistura.

Não implementei TLS nem login, nem página web; tudo se resume a uma conexão TCP. Não há necessidade de nenhuma proteção extra, o que poupa recursos da MCU, permitindo assim o aprimoramento do programa em si. Para validar a mensagem, são recebidos 6 bytes, com um inicializador, o código CMYK (que virá do picker) e o finalizador:

^CMYK$

Para testar, criei um pequeno script Python:

#!/usr/bin/env python

import socket
import time
def client_program():
    host = "192.168.1.209"   
    port = 1234  

    client_socket = socket.socket() 
    client_socket.connect((host, port)) 

    message = b'\x5e\xf1\x5f\x30\x05\x24'
    client_socket.send(message)  
    
    
    time.sleep(3)
    client_socket.close()  

    
if __name__ == '__main__':
    client_program()

O delay é necessário, porque a leitura é feita enquanto o client estiver com a porta aberta na comunicação. Se enviar a mensagem e fechar imediatamente, será um problema para o misturador de cores.

Material do misturador de cores CMYK

Com esse artigo será possível reproduzir plenamente o projeto, inclusive pode-se fazer algumas modificações para reduzir o custo, mas em contrapartida perde-se em aparência, hum? Utilizei material de primeira em todos os pontos e os relacionei pouco a pouco, conforme fui tratando com os parceiros. Vamos à lista.

AFSmartControl – Placa ESP32 com display touch da AFEletronica

processador do misturador de cores

Poderia opcionalmente utilizar pontes H para esse projeto, o que permitiria reversão dos motores. Porém, nem a reversão e nem PWM serão necessários, de modo que acaba ficando mais barato e mais prático utilizar uma placa com tudo onboard para montar no case.

A AFSmartControl é uma placa produzida com fim industrial que conta com bem mais recursos do que precisamos, mas é fundamental que a placa seja confiável, ainda mais para um projeto que será permanente. Essa placa você encontra aqui.

O display touch dela é fundamental, mas discorrerei a respeito mais adiante. Uma apresentação mais detalhada da placa pode ser vista nesse outro artigo.

Bomba peristáltica Robocore

bomba peristáltica do misturador de cores

São quatro cores, portanto quatro bombas peristálticas. Essas bombas peristálticas “evaporam” do site da Robocore, sem exagero. Se pretende reproduzir o projeto ou simplesmente fazer um dispenser de líquidos ou álcool, aproveite para pegar logo porque acabará, e quando o estoque tiver que ser renovado, o preço pode ser outro, graças à crise atual que vivemos. Já escrevi um artigo detalhado de operação da bomba peristáltica da Robocore, no artigo “Dispenser com Arduino usando bomba peristáltica“.

Será necessário adquirir mangueiras de silicone para expansão da bomba peristáltica. Casas de aquarismo são provavelmente o lugar mais barato que você vai encontrar.

Fonte de alimentação

fonte de alimentação do misturador de cores

A fonte de alimentação precisa ser forte, não dá pra brincar com fonte de celular e nem pense em alimentar motores diretamente na placa, ok? A fonte recomendo que seja adquirida na Magir Fastshop, sendo a de 12V@5A (no mínimo). A ligação é a mais básica possível: VCC no lado direito da traseira do motor, lado esquerdo do motor ao NA do relé. GND ao COM do relé e só. Mesmo estando diretamente ligado ao relé e, talvez por ser GND comum, os motores estavam dando retorno e causando anomalia. Coloquei um diodo inversamente polarizado entre os contatos do motor, e resolvido o problema.

Case e recipientes para as tintas

a melhor CNC do mercado - ECNC

Aqui tenho uma vantagem extra; como tenho uma CNC laser de 100W (magnífica por sinal) da ECNC, pude projetar um case sob medida para cortá-lo a posteriori. Se pretende adquirir uma CNC laser, recomendo fortemente a ECNC por ser indústria nacional, e a fabricação é de primeira linha. Todos os componentes são de altíssima qualidade, e a estrutura é impecável (é o prazer de comprar um carro). Conheça a L-560 e outras mais! Se quer saber mais sobre essa CNC, leia o artigo “Qual CNC laser Comprar“.

É importante considerar uma boa CNC laser quando for comprar, porque por mais que o laser tenha precisão de 0.01mm, o hardware precisa entregar um bom controle. E é aí que começam as atrocidades; desalinhamento e inclinação no corte, círculos que não fecham no ponto certo e muitas outras coisas. Se for comprar uma chinesa então, hummmm. As CNCs da ECNC são o melhor hardware que você vai encontrar, digo sem receio, pois estou plenamente satisfeito com minha L-560.

acrílico colorido sinteglas

O material do case e para os recipientes é acrílico, escolhido por diversos motivos: é material nobre, já sai com acabamento final do corte, é durável e bonito. E também não pode ser qualquer acrílico. Existem dois tipos principais de acrílico; o extrusado e o cast. O cast é mais durável, resistente e no caso dos acrílicos cast da Sinteglas, tem mais de 500 tipos diferentes. Visite o site (de infindável manutenção, mas sem dúvidas do melhor acrílico). Se tem curiosidade em saber como o acrílico cast é fabricado, dê uma conferida nesse vídeo em nosso canal Dobitaobytebrasil no Youtube. O acrílico escolhido para esse projeto foi o Sinteglas MP979, porém não chegou em tempo para a execução, então usei um acrílico preto.

Aproveite pra dar uma olhada também no perfil da Sinteglas no Instagram.

Os recipientes para a tinta serão os copos de isopor, vendidos em lojas de recipientes de marmita, escritório e festas. No caso, estou usando o copo de 50ml e 100ml. A tinta será alocada em tubetes de 13cm, que cabem 50ml. Esses tubetes são fáceis de encontrar em docerias, casas de artigos para festas e muitas lojas online. Também acoplei uma tampa de tubete à saída da mistura, de modo que se desejar tirar uma amostra pequena, pode-se utilizar um tubete curto, como o mostrado no vídeo.

Coletor de amostra de cores

Sensor de cores do color picker

Podemos escolher a cor a partir de uma mistura no display (como mostrarei mais adiante), ou enviar via wifi para o misturador de cores. Para enviar por wifi, preferi fazer um dispositivo de mão com um sensor de cores TCS34725, adquirido no Baú da Eletrônica. Já escrevi sobre esse sensor, como pode ser visto nesse outro artigo.

Placa para o pickerprocessador do color picker

Claro, uma MCU adicional será necessária. Achei ideal utilizar a Heltec Stick, que é compacta, vem com LoRa, tem um display discreto e é bastante compacta. Essa placa é um ESP32, o que permitiu fazer as estripulias que descrevo mais a frente. Essa placa está disponível na CurtoCircuito, através desse link.

Placa de alimentação

Não acaba por aí. Para ser um dispositivo de mão, precisa ser alimentado por bateria. Achei um módulo para bateria ideal para utilizar nesse projeto, que é o Dual Shield ESP32 para bateria li-ion, que se encontra nesse link da Saravati. Nas laterais tem diversas saídas GND e 5V de um lado, GND e 3V3 do outro. Pulsando o botão (do lado oposto à chave de ligamento) a placa é energizada. Duas baterias de 3.7V com 6800mAh, com o ESP32 consumindo uns 160mAh são quase 43 horas ligado ininterruptamente. O color picker não será um transtorno como um Magic Mouse da Apple, que mal dura um dia ligado.

Nas saídas 5V, até 3A podem ser consumidos. Na 3V3, o limite é de 1A. O único cuidado a se ter é o posicionamento da bateria, mas na própria placa está indicado o polo, assim como na bateria.

A qualidade desse banco de baterias é notória. Na parte de baixo estão dispostos os componentes e 4 LEDs que ligam ao energizar uma placa, mas confesso que ainda não sei a função deles; se é porcentagem de carga ou outra coisa. No canto oposto que está a chave de ligamento tem duas portas USB; uma micro-USB e uma USB-C. A micro-USB é carregamento, a USB-C também não tenho certeza, mas é fácil testar com um dispositivo que tenha USB-C.

A corrente de carregamento fica entre 0.6 e 0.8A. A placa também possui um LED indicador de carga, sendo verde para carga total e vermelho para descarregado. Essa placa é incrível, porque não é necessário extrair mais as baterias para carregá-la; ela alimenta, ela carrega!

As baterias eu já as tinha, comprei pelo Mercado Livre e são bem baratinhas.

pack de bateria do color picker

Finalizada a lista de hardware, hora de falarmos da parte lógica do projeto.

Funções do display touch ILI9341

Esse display é fantástico e escrevi sobre o ILI9341 recentemente. Acredito que seja uma leitura importante, já que estamos tratando do assunto de cores luz e cores pigmento, mas vou citar alguns pontos importantes aplicados à lógica.

Áreas quentes

A área quente é área configurada para responder ao toque. Repare na imagem:

display do misturador de cores

Nesse print ainda não havia implementado a exibição do IP (durante o desenvolvimento já teve IP na tela), a amostra mínima era 10 ml mas mudei para 1 ml e o avanço que era de 5 em 5 ml, agora é de 1 em 1 ml. Além disso, agora o display exibe o valor hexadecimal do RGB. Olha que interessante a quantidade de conversões; RGB 24 bits para RGB 16 bits, RGB 24 bits para CMYK, CMYK para RGB 16 bits e RGB 24 bits para hexa. Ok, hexadecimal é apenas a mudança da base numérica, mas foi necessário um trabalhinho mínimo para isso:

void rgbToHexaString(){
  char colorBuffer[9];
  snprintf(colorBuffer, sizeof(colorBuffer), "%02X %02X %02X", RGBarray[0], RGBarray[1], RGBarray[2]);
  hexaColor = "#" + String(colorBuffer);
}

A imagem da esquerda é a tela natural, constituída a partir de um exemplo da biblioteca TFT_eSPI, que considero uma das melhores (se não a melhor das) bibliotecas para display. Essa biblioteca é altamente responsiva e consome poucos recursos. O exemplo utilizado foi o TFT_Meter, do qual removi 2 meters lineares e modifiquei um pouco o visual do meter analógico. O background, claro, tive que implementar 100% para se tornar um projeto.

Operação pelo display

Após modificar a distribuição dos componentes da tela, adicionei as áreas quentes do toque. No meter analógico, clicando na esquerda ou direita temos o decremento e o incremento (respectivamente) do volume em ml da mistura. Deixei configurado o mínimo para 1 ml para ter margem de mistura. Dependendo da cor selecionada, um volume inferior a 1ml será extraído, mas quanto mais baixa for a amostra, maior a margem de erro. Prefira tirar amostras a partir de 5ml, se não for resultar em grande desperdício.

Sobre as letras “C”, “M”, “Y” e “K” no display, aumenta-se a porcentagem da respectiva cor. Nos valores percentuais na base do display, reduz-se esses valores. Se o volume marcado no display for de 10ml e uma das cores estiver marcado com 50%, significa que dessa cor será extraído 5ml. Por isso, tenha em mente que o volume final extraído corresponde à soma percentual das cores.

O botão logo abaixo do valor de medida é para iniciar o processo de mistura. Ainda que seja enviado o valor da mistura remotamente, a execução só será possível através do toque no display.

Se desejar selecionar uma cor manualmente ou fazer algum ajuste fino, pode-se fazer isso clicando sobre C, M, Y e/ou K. Para reduzir o valor, basta clicar na área quente do rodapé.

Funções da placa AFSmartControl

Leia esse artigo para ver os detalhes da placa. Agora vou apenas citar alguns recursos, que estão sendo utilizados nesse projeto.

O controle dos relés é bastante prático, uma vez que a placa da AFEletronica tem um PCF8574 para tal. O endereço varia conforme o modelo do PCF (8574A ou 8574AT). Na documentação da placa estão especificados os endereços. No meu caso, está no endereço 0x27.

Os bits dos relés são do 4 ao 7. Estou fazendo o controle usando bitwise, de modo que eu possa executar assincronamente os motores e extrair as tintas rapidamente. Se não conhece o PCF8574 ou não tem intimidade com bitwise, recomendo a leitura do artigo “Dominando PCF8574 com Arduino“. É a mesma coisa para outras MCUs e no Raspberry mostrei esse controle por shell, cujo vídeo relacionado é esse. Só para ter uma ideia, a variável dos bits do PCF são ajustadas assincronamente, o que mais uma vez fez existir a necessidade de um mutex para garantir o acesso privilegiado, evitando colisões no acesso. O ajuste com bitwise é feito levantando o respectivo bit, dessa maneira (parcial da função):

void pump(void *pvParameters){
   uint8_t &pcf_bit = *(uint8_t*) pvParameters; //bit do pcf a manipular
   xSemaphoreTake(myMutex,portMAX_DELAY); //protege tudo que for ser manipulado
   pump_params.running += 1; //a partir de agora nenhuma alteração é permitida até voltar a 0.
   pump_params.pcf_value = pump_params.pcf_value&~(1<<pcf_bit); //baixa o bit (liga com 0)
   Wire.beginTransmission(PCF_ADDR); //inicia comunicação i2c no endereço do PCF
   Wire.write(pump_params.pcf_value); //escreve o valor recém modificado
   Wire.endTransmission(); //finaliza a transmissão
   xSemaphoreGive(myMutex); //libera os recursos

Aqui faço uma cópia do ponteiro de *pvParameters para um endereço de memória identificado por pcf_bit. Essa é uma das formas de utilizar parâmetros na task do ESP32, mas já escrevi um artigo dedicado a isso (“Passando parâmetros através de task no ESP32“). O código final foi melhorado em algumas vezes e esse cast acima não é mais feito assim, mas vale como exemplo.

O mutex é uma “trava de segurança” (ainda preciso acertar essa função, mas estou implementando conforme penso para depois acertar, não estranhe o formato agora). Já escrevi sobre mutex em dois outros artigos; “Como utilizar mutex no FreeRTOS” e também na apresentação do CLP i4.0 da VDC. Se olhar no código, pode parecer estúpida a utilização do mutex dentro da task apenas, mas ela é uma função iniciada múltiplas vezes, com diferentes identificadores.

Sem uma instrução prévia, a linha pump_params.pcf_value parece estranha, mas bitwise é uma excelente maneira de lidar com bits. Veja mais em “Dominando PCF8574 com Arduino” (serve para qualquer placa usando C/C++).

FreeRTOS e ESP32, uma mão na roda

E para um projeto como esse, não seria viável utilizar outra coisa que não um ESP32. O protocolo de comunicação poderia ter sido implementado por bluetooth, mas como bluetooth consome recursos demasiados, preferi fazê-lo por WiFi, mas é uma opção. O ESP32 possui 2 núcleos que podem trabalhar a até 240MHz, além de ter um monte de memória, coisa que flexibiliza a programação. Não usei o sistema de arquivos do ESP32, mas o código não chega a ser genérico, pois estou utilizando tasks para o processamento assíncrono. Por fim, um recurso importante adicionado à programação foi o controle de acesso a algumas variáveis globais, que não devem ser acessadas simultaneamente, por isso implementei uma trava com mutex. No artigo da CLP i4.0 da VDC exemplifiquei o uso, acredito que seja importante dar uma olhada para posteriormente entender o código do misturador de cores CMYK.

Picker RGB para CMYK com ESP32

Claro que esse haveria de ser um projeto à parte. Por essa razão, publiquei primeiramente um artigo exclusivo com o ESP32 Heltec Stick da CurtoCircuito, recomendo a leitura e duvido que você não quererá um também. A CurtoCircuito é um dos parceiros que mais tem variedade de ESP32, recomendo uma visita ao site. Quanto ao próprio Heltec Stick, vá direto ao produto através desse link.

A qualidade de captura do picker é realmente satisfatória. Fiquei impressionado porque tenho uma certa habilidade para misturar cores manualmente (como citei no início, fui cartunista) e não tinha essa noção de proporção percentual. Quando vi os valores de leitura, achei que ia dar errado. Bem, pra não dizer que está perfeito, parece que a proporção de preto não está casando. Visualmente está muito escuro, mas vamos ver agora na amostragem.

Um último ponto a considerar é que por melhor que seja a leitura, fatores externos influenciarão na amostra; luz fluorescente, luz do sol etc. Pensando nesses detalhes, o display dá a possibilidade de fazer o ajuste fino antes de tirar a amostra. Como citado em algum trecho do artigo, o display é RGB565; talvez 16 bits não sejam o suficiente para um bom retorno visual, mas se a amostra tirada não estiver ao agrado, basta corrigir novamente e tirar outra amostra.

Comunicação do color picker com o color mixer

O misturador de cores está com WiFi configurado no modo AP. O color picker se conecta ao misturador de cores para enviar a amostra. Quando o faz, os valores do display do misturador de cores são ajustados, mas o único meio para iniciar o processo de extração é clicando em Iniciar no display. Isso evita um ataque externo.

Durante a extração, não é possível alterar os valores ou clicar em iniciar novamente. A comunicação com o color picker ainda ocorrerá, mas não haverá mudanças durante a execução, portanto esse é mais um passo de segurança.

O color picker não é componente essencial, mas fica muito legal para o projeto. Ainda não fiz o case dele, é mais difícil comportar seus componentes e fazê-lo portátil, mas quando estiver com essa questão resolvida, volto a escrever sobre ele.

Projeto do case

A Robocore oferece também o desenho técnico da bomba peristáltica (no rodapé estão os arquivos), o que facilita tirar as medidas para fazer o case. De qualquer modo, eu as havia pego com um paquímetro e o desenho fiz no QCAD. O projeto foi idealizado considerando as dobras, feitas na dobradeira de acrílico. A fachada no desenho fica assim (apenas para ter uma ideia):

O programa QCAD tem versões gratuitas e pagas. A paga tem alguns recursos adicionais dos quais eu faço uso, mas a versão gratuita é mais que o suficiente para a maioria dos projetos que criarmos. No vídeo estão dispostos alguns fragmentos do processo de produção, mas de qualquer modo, deixo essa imagem do resultado interno:

lado interno do misturador de cores

Como a intenção inicialmente é utilizar corantes para confeiteiros, invés de abertura superior nos recipientes das cores, fiz a entrada lateral. Não fica “bonitão” e é bem artesanal essa parte, mas o importante é que é funcional.

recipiente de tinta do misturador de cores

Código-fonte do misturador de cores CMYK

O programa foi feito utilizando o plugin PlatformIO no VS Code. Não tem IDE melhor; autocomplation, referências às documentações e todos os recursos que uma IDE pode oferecer. Baixe-o gratuitamente no site oficial.

O código do projeto ficou realmente grande para ser publicado em um artigo, por isso deixo o link do repositório no Github, cujo projeto chamei de rgb2cmyk.

Calibragem do volume

Dependendo de fatores como comprimento da mangueira, pode ser que haja necessidade de recalibrar uma ou mais bombas. O procedimento já está descrito no artigo de dispenser com Arduino usando bomba peristáltica. Tire uma amostra em ML de cada uma das bombas para ver se todas estão calibradas e altere a variável de tempo (one_ml) se for preciso.

Calibragem da cor

Tenha em mente que ciano não é “azulzinho”, magenta não é “vermelhinho” e não prefira “amarelo ouro” porque é mais bonito. O padrão “tem” que ser ciano, magenta, amarelo e preto. O tubete de 13cm cabe 50ml de tinta. O programa está configurado para tirar até 100ml por cor, de modo que se pretende fazê-lo, adicione um recipiente externo maior para as tintas.

No meu exemplo estou diluindo os corantes em água, mas para colorir bolos e glacês tem que ser puro. Existem corantes em pó (que não servem para esse projeto) e também os corantes em gel. As bombas peristálticas conseguem puxar materiais até uma certa viscosidade, mas não sei se é uma boa ideia usar corante gel para pequenos volumes – um único bolo, por exemplo.

Quanto mais diluído for, mais clara a cor ficará e obviamente o resultado não será o mesmo da amostra pretendida, mas algo da mesma escala, considerando a variação de tonalidade. Por isso, sempre que for fazer a mistura, garanta a uniformidade das partes água/corante, exceto vá usar mesmo os corantes puros.

Primeira extração

No primeiro uso ou sempre que trocar a tinta, faça uma primeira extração para encher a mangueira. Faça a primeira extração com o case aberto e repare se não há vazamento ou bolhas durante o processo. Se houver bolhas, significa que está vazando ar. Corrija o problema e repita o processo.

Se a extração não estiver ocorrendo, verifique se a mangueira está dobrada. Se não estiver e a bomba peristáltica estiver rodando, então o problema é que está vazando tanto ar que a bomba não está dando conta de escovar o líquido.

Higienização

A higienização pode ser feita com álcool 70, encontrado em brew shops e em alguma casas de produtos de limpeza. Ao terminar o uso, descarregue as mangueiras, ligando uns 3ml em todas as cores, depois coloque o álcool nos recipientes e faça uma nova extração. Deixe por uns 15 segundos parado assim que terminar o processo, então extraia o restante do álcool das mangueiras.

Vídeo do misturador de cores CMYK

E após todo esse trabalhão que levou quase 3 semanas de esforço, mais de 50 revisões durante a produção do artigo, horas de gravação e edição de vídeo, o projeto ficou pronto e pode ser visto em nosso canal DobitaobyteBrasil no Youtube – mas por favor – deixe seu like, inscreva-se, clique no sininho para receber notificações e compartilhe tanto quanto possível para justificar o gigantesco esforço, ajudando chegar a mais leitores. E, sempre que puder, prestigie o mercado nacional, adquirindo produtos de nossos parceiros, que propiciam artigos elaborados como esse!

 

Revisão: Ricardo Amaral de Andrade

Djames Suhanko

Sobre o autor: Djames Suhanko é Perito Forense Digital. Já atuou com deployer em sistemas de missão critica em diversos países pelo mundão. Programador Shell, Python, C, C++ e Qt, tendo contato com embarcados ( ora profissionalmente, ora por lazer ) desde 2009.