FLProg - Integração independente ao programa de controladores personalizados


Durante muito tempo, o projeto FLProg não foi abordado em Habré. Isso se deve à falta de tempo para escrever artigos e até a meus próprios problemas pessoais. Mas o projeto não está morto, vive e se desenvolve. Em média, uma vez por mês, a próxima versão do programa é lançada. Desde a última publicação , a renderização do circuito foi completamente refeita (graças a isso, os frisos foram eliminados durante a renderização), o sistema de referência cruzada para o projeto e um sistema para analisar o projeto quanto a erros. O próprio código do programa foi portado para uma versão mais recente da linguagem de programação. Devido a isso, do lado positivo (do meu ponto de vista, é claro, bem, os usuários me apoiam), a interface do programa mudou. Muitos blocos interessantes foram adicionados. Escala de esquema implementada e pesquisa de bloco.

Mas, ainda assim, o principal problema do projeto é que o desenvolvedor do programa é uma pessoa (esse sou eu), e o número de diferentes placas controladoras, sensores, sensores, placas de expansão fabricadas pelos chineses e recentemente por nossos fabricantes está em constante crescimento. E os usuários querem experimentá-los ou usá-los em seus projetos. Para dispositivos periféricos, ao mesmo tempo, esse problema foi mais ou menos resolvido por mim com a ajuda da criação de um editor de blocos personalizado. Esta etapa, como se costuma dizer, disparou, e agora, quase na maioria das placas periféricas existentes, na Internet ou no fórum do programa , você pode encontrar o bloco de usuário correspondente. Bem, ou no mesmo fórum (ou em um grupo em Vkontakte ) peça aos gurus locais que escrevam um. Geralmente você pode, de uma forma ou de outra, concordar.

Agora é hora de resolver o segundo problema - estas são placas controladoras.

Recentemente, foi lançada uma versão beta do programa com o número 6.0. Nesta versão, o editor de descrições do usuário dos controladores é implementado. Como nos blocos personalizados, as descrições podem ser agrupadas em bibliotecas, salvas como descrições separadas, bem como bibliotecas inteiras como um arquivo e compartilhadas.

Com este post, inicio uma série de pelo menos dois posts nos quais consideraremos como usar este editor. No primeiro artigo, com a permissão do shiotiny, tentarei descrever o quadro do ShIoTiny. No segundo artigo, tentaremos criar um analógico de um controlador industrial real e descrevê-lo.

Então, vamos começar.

Abra o programa FLProg. No menu "Ferramentas", selecione o "Editor de descrições personalizadas do controlador".



A janela do editor de descrição é aberta.

Descrições personalizadas podem ser combinadas na biblioteca com qualquer profundidade de aninhamento. Portanto, primeiro criamos uma biblioteca de descrição.



Defina o nome da biblioteca.



Depois disso, criaremos uma descrição do controlador na biblioteca.



E dê-lhe um nome:



Ao criar uma descrição do controlador, chegamos imediatamente ao ramo dos parâmetros gerais.



Aqui podemos mudar o nome, definir o tipo de CPU, definir o tamanho da EEPROM, alterar o número da versão da descrição.

Como a placa ShloTiny é baseada no controlador ESP8266, nós a selecionamos. Ao escolher um controlador, o volume EEPROM correspondente é automaticamente afixado. Se necessário, esse valor pode ser alterado. O número da versão padrão para a nova descrição é definido como 1.

No futuro, ao alterar as descrições existentes, é recomendável alterá-lo na direção do aumento. Ao usar esta descrição em um projeto, o programa comparará a versão da descrição no projeto e na biblioteca. Se o número da versão da descrição na biblioteca for maior que no projeto, o item para atualizar a descrição no programa aparecerá no menu "Projeto" do programa. Se vice-versa, um item aparecerá para atualizar a descrição na biblioteca. Bem, se a descrição do controlador usado no projeto não for encontrada na biblioteca, o item para inserir a descrição do projeto na biblioteca aparecerá no mesmo menu.

Também neste tópico, você pode escrever uma descrição em texto do controlador que ajude na sua seleção.

Para aplicar as alterações feitas antes de mudar para outra ramificação dos parâmetros do controlador, clique no botão "Aplicar". Se isso não for feito, as alterações não serão salvas.

Agora considere o diagrama de circuitos da placa ShloTiny.



A placa possui três entradas digitais, três saídas digitais, uma entrada analógica e uma entrada para o sensor. Um total de oito conclusões do conselho.

No editor, vá para o ramo "Conclusões do controlador" e defina o número de conclusões. Não se esqueça de clicar no botão "Aplicar" depois disso.



O programa irá gerar o número necessário de conclusões. Passamos para o primeiro deles.



Nesta ramificação, você pode especificar um nome de saída alternativo, que será exibido no programa. Se estiver ausente, o programa exibirá PinN onde N é o número do pino na lista de pinos. Eu recomendo que você escreva uma inscrição no quadro no campo nome alternativo. Isso facilitará a compreensão de que conclusão está sendo tirada. Para a placa descrita, colocaremos o valor da Entrada1 de acordo com o diagrama de circuitos. Portanto, neste tópico, você pode escrever uma descrição individual da saída, por exemplo, para indicar os recursos de sua aplicação. Se necessário, você também pode especificar um alias para a saída, que será exibido no programa entre colchetes após o nome da saída.

Depois de fazer as alterações, não se esqueça de clicar no botão "Aplicar". Pelo mesmo princípio, vamos chamar as conclusões restantes.



No mesmo ramo dos principais parâmetros de saída, as funções que ele executa são adicionadas a ele.



As seguintes funções podem ser atribuídas a cada pino.



  • I2C é uma função de um dos pinos de barramento I2C (SDA ou SCL).
  • O SPI é uma função de um dos pinos do barramento SPI (MISO, MOSI, SCK, SS).
  • UART é uma função de um dos pinos da interface UART (RX ou TX).
  • Função de entrada analógica
  • Função de saída analógica (ainda não usada no FLProg, lista de pendências para o futuro).
  • Função de entrada / saída digital.

Atribua a função de entrada / saída digital do pino 1. Ao atribuir uma nova função (ainda não configurada) à saída, a ramificação "Erros" aparecerá na árvore do controlador e todo o caminho para a ramificação da função incorreta ficará vermelho. No ramo "Erros", você pode ver uma lista de erros encontrados na descrição do controlador.



Nesse caso, a entrada 1 na função “Entrada / saída digital” não especifica o número dessa entrada como digital. Mudamos para o ramo desta função (no futuro, pretendo fazer uma transição direta para o ramo desejado quando clicar em um erro).



De acordo com o diagrama de circuito da placa, a saída “Input1” é conectada ao pino GPIO2 do controlador. Nós inserimos esse valor no campo "Número da entrada digital". Ao compilar um projeto, esse valor será inserido no código. Como o uso desta entrada como saída não é fornecido, removemos a caixa de seleção "Pode ser usada como saída". Como sempre, clique no botão "Aplicar". Da mesma maneira, configure as outras duas entradas digitais. Então vá para a saída da entrada analógica "ADC1" e adicione a função "Entrada Analógica".



Nas configurações desta função, você deve especificar o número desta saída como uma entrada analógica. De acordo com o esquema, este é 0 (em ESP8266 é um).



Em seguida, vá para a configuração de saída "1WIRE". Aqui, adicionamos a função de entrada / saída digital, mas proibimos o uso de entrada e saída. Como resultado, ele estará disponível para seleção apenas nos blocos de sensores e não estará disponível ao criar entradas e saídas.



As configurações das saídas “K1” - “K3” são semelhantes às configurações das entradas “Input1” - “Input3” somente no caso de saídas que são proibidas de serem usadas como entrada.





Vá para o ramo "Imagens". Nele, podemos adicionar imagens carregadas na descrição do controlador, por exemplo, com a aparência do controlador, pinagem etc.

Observe que as imagens são carregadas diretamente na descrição do controlador e são armazenadas em um projeto criado usando-o. Portanto, não carregue imagens grandes. Isso implicará em um aumento no tamanho do projeto e afetará a velocidade de sua abertura.

A imagem é adicionada usando o botão "Adicionar imagem".



Depois de selecionar e carregar uma imagem (apenas o formato PNG é suportado), um ramo separado é criado para cada imagem na árvore. Nesta ramificação, você pode especificar um nome para a imagem baixada, que será exibida nas informações do controlador.



Se necessário, você pode carregar várias imagens e configurá-las na ordem desejada.





Passamos para o ramo "Blocos padrão".



Esta ramificação mostra os blocos que podem ser representados na biblioteca de blocos padrão do programa, de acordo com as configurações atuais do programa. O que isso significa? Alguns dos componentes do programa destinam-se apenas a certos tipos de CPUs. E sua disponibilidade depende do processador selecionado. Além disso, os blocos projetados para trabalhar com SPI, I2C, UART aparecerão nesta lista somente se as funções correspondentes forem adicionadas aos pinos do controlador. Os blocos projetados para trabalhar com a EEPROM aparecerão apenas se o tamanho da EEPROM especificado na ramificação dos parâmetros gerais do controlador for maior que zero ou se a função I2C for adicionada aos pinos do controlador. Por padrão, todos os blocos da biblioteca são proibidos de usar (marcados em laranja). Você pode permitir o uso de um bloco separado ou de toda a pasta, realçando a ramificação necessária e clicando no botão "Permitir" ou no menu de contexto.



Quando você permite que um bloco ou pasta de blocos seja exibido no programa, eles são pintados de preto.

O bloqueio de um bloco ou de uma pasta separada é proibido da mesma maneira.



Em uma pasta na qual nem todos os blocos podem ser exibidos, eles são marcados com três asteriscos antes e depois do nome.

Proibimos o uso de motores, relógios em tempo real, displays, unidades de controle IR, sensores (exceto os sensores DS18B20 e DHT22, pois o desenvolvedor da placa até agora apenas anunciou seu suporte), chips de expansão e um alto-falante piezo.



Faremos o mesmo para a linguagem LAD



Não se esqueça de aplicá-los depois de fazer alterações.

As ramificações restantes da descrição do controlador serão discutidas no próximo post, enquanto as configurações atuais são suficientes para usar essa placa específica no programa FLProg.

Por enquanto, vou dizer brevemente que o ramo "Blocos especiais" é usado para carregar blocos personalizados na descrição, que será mostrada na biblioteca de blocos padrão do programa ao usar este controlador. A ramificação "Código especial" é usada para registrar o código que sempre será inserido no código compilado e a ramificação "Bibliotecas especiais" é usada para carregar bibliotecas na descrição do controlador, que será carregada na pasta \ libraries ArduinoIDE com a qual o programa trabalha.

Após todas as alterações, salve a biblioteca de descrição do controlador.



Agora vamos tentar usar a descrição do controlador que criamos.
No programa FLProg, criamos um novo projeto para o controlador.



Abra a janela de seleção do controlador.



E selecione a descrição que criamos.



Ao escolher um controlador, você pode ver suas imagens e, se necessário, salvar o necessário em um arquivo.





Você também pode ver outros parâmetros



Após selecionar o controlador, confirme sua seleção:



Como resultado, a janela principal de trabalho do projeto é aberta, configurada de acordo com o controlador selecionado.



O objetivo desta publicação não inclui a tarefa de treinamento para trabalhar com o programa FLProg. Isso está bem descrito nas minhas postagens anteriores , no site do projeto e no fórum do projeto . Além disso, já existem muitos canais no YouTube onde são postados tutoriais em vídeo sobre como trabalhar com o programa. Por exemplo, um canal muito bom “Key to Arduino” está agora conduzindo uma série de lições, com uma apresentação muito boa do material.

Portanto, por exemplo, simplesmente criamos um projeto simples e tentamos compilá-lo.
Primeiro, adicione a entrada do controlador.



Somente as conclusões que nos permitiram trabalhar nessa capacidade estão disponíveis para seleção como insumo.



Em seguida, crie uma saída digital. Apenas conclusões permitidas também estão disponíveis aqui.



Montamos o circuito para que, quando o botão da Entrada1 (Entrada 1) for pressionado, o relé K1 (Relé1) seja ativado.
Também puxamos a unidade para ler informações do sensor DS18B20 em uma placa de circuito em uma placa separada.



Vá para as configurações do bloco. Ao criar o novo barramento OneWire, vemos que todas as entradas / saídas digitais estão disponíveis para seleção. Esta é uma falha na versão 6.0. Mas como essa versão ainda tem status beta, é desculpável. Na versão 6.1, será possível proibir o uso de um pino como sensor, sensor ou para chips de expansão. Além disso, no próximo post, mostrarei outra maneira de resolver esse problema. Por enquanto, selecione 1WIRE pin.



Nós configuramos o sensor para definir o endereço através da matriz.



Nós inserimos uma nova placa na frente da primeira e puxamos o bloco “OneWire Bus Scan” nela.



Nós o configuramos no mesmo barramento OneWire e no mesmo array em que a unidade de leitura do sensor DS18B20 está configurada.



Montamos um esquema para um único início de uma varredura de barramento quando o controlador é iniciado, usando o bloco R do gatilho (seleção da borda principal).



Em uma placa com uma unidade de leitura de dados do sensor DS18B20, montamos um circuito de relé on / off com histerese. Para isso, usamos dois comparadores e um gatilho SR. Graças a esse esquema, o relé 2 liga quando a temperatura cai abaixo de 10 graus e desliga quando a temperatura sobe acima de 20 graus.



Iniciamos o esquema de compilação.



Como resultado, o código resultante será aberto no IDE do Arduino. Como placa, selecionamos NodeMCU, no qual o mesmo chip está instalado como no ShloTiny. A verificação do código mostra que ele está correto e pode ser baixado.



Código compilado
#include <OneWire.h> extern "C" { #include "user_interface.h"; } OneWire _ow13(13); byte _FLPArray133289689[9]; unsigned long _d18x2x1Tti = 0UL; float _d18x2x1O = 0.00; bool _trgr1 = 0; bool _bounseInputD2S = 0; bool _bounseInputD2O = 0; unsigned long _bounseInputD2P = 0UL; bool _trgrt1 = 0; bool _trgrt1I = 0; bool _sowb1_needScan = 0; bool _sowb1_ost = 0; bool _sowb1_Out_1 = 0; void setup() { pinMode(2, INPUT); pinMode(12, OUTPUT); pinMode(14, OUTPUT); _bounseInputD2O = digitalRead(2); } void loop() { bool _bounceInputTmpD2 = (digitalRead (2)); if (_bounseInputD2S) { if (millis() >= (_bounseInputD2P + 40)) { _bounseInputD2O = _bounceInputTmpD2; _bounseInputD2S = 0; } } else { if (_bounceInputTmpD2 != _bounseInputD2O ) { _bounseInputD2S = 1; _bounseInputD2P = millis(); } } //:1 if (1) { if (_trgrt1I) { _trgrt1 = 0; } else { _trgrt1 = 1; _trgrt1I = 1; } } else { _trgrt1 = 0; _trgrt1I = 0; }; if (_sowb1_needScan) { if ( _oneWireSeach (_FLPArray133289689, _ow13)) { _sowb1_Out_1 = 1; } _ow13.reset_search(); _sowb1_needScan = 0; } if (_trgrt1) { if (! _sowb1_ost) { _sowb1_ost = 1; _sowb1_needScan = 1; _sowb1_Out_1 = 0; } } else { _sowb1_ost = 0; } //:2 digitalWrite(12, !(_bounseInputD2O)); //:3 if (_isTimer(_d18x2x1Tti, 1000)) { _d18x2x1Tti = millis(); _d18x2x1O = _readDS18_ow13(_FLPArray133289689, _FLPArray133289689[8]); } if (((_d18x2x1O)) > (20)) _trgr1 = 0; if (((_d18x2x1O)) < (10)) _trgr1 = 1; digitalWrite(14, _trgr1); } bool _isTimer(unsigned long startTime, unsigned long period ) { unsigned long currentTime; currentTime = millis(); if (currentTime >= startTime) { return (currentTime >= (startTime + period)); } else { return (currentTime >= (4294967295 - startTime + period)); } } float _convertDS18x2xData(byte type_s, byte data[12]) { int16_t raw = (data[1] << 8) | data[0]; if (type_s) { raw = raw << 3; if (data[7] == 0x10) { raw = (raw & 0xFFF0) + 12 - data[6]; } } else { byte cfg = (data[4] & 0x60); if (cfg == 0x00) raw = raw & ~7; else if (cfg == 0x20) raw = raw & ~3; else if (cfg == 0x40) raw = raw & ~1; } return (float)raw / 16.0; } float _readDS18_ow13(byte addr[8], byte type_s) { byte data[12]; byte i; _ow13.reset(); _ow13.select(addr); _ow13.write(0xBE); for ( i = 0; i < 9; i++) { data[i] = _ow13.read(); } _ow13.reset(); _ow13.select(addr); _ow13.write(0x44, 1); return _convertDS18x2xData(type_s, data); } bool _oneWireSeach (byte array[], OneWire ow ) { byte temp[8]; byte i; if ( !ow.search(temp)) { return false; } if (OneWire::crc8(temp, 7) != temp[7]) { return false; } switch (temp[0]) { case 0x10: array[8] = 1; break; case 0x28: array[8] = 0; break; case 0x22: array[8] = 0; break; default: return false; } for ( i = 0; i < 8; i++) { array[i] = temp[i]; } return true; } 


Descrição do controlador ShloTiny para o programa FLProg

Terminaremos esta lição. No próximo post, tentaremos descrever algo mais sério e mais próximo dos controladores industriais "reais".

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


All Articles