FLProg: integración independiente en el programa de controladores personalizados


Durante mucho tiempo, el proyecto FLProg no ha sido cubierto en Habré. Esto se debe a la falta de tiempo para escribir artículos e incluso a mis propios problemas personales. Pero el proyecto no está muerto, vive y se desarrolla. En promedio, una vez al mes, se lanza la próxima versión del programa. Desde la última publicación , la representación del circuito se ha rehecho por completo (gracias a esto, se eliminaron los frisos durante la representación), apareció el sistema de Referencia cruzada para el proyecto y un sistema para analizar el proyecto en busca de errores. El código del programa en sí fue portado a una versión más reciente del lenguaje de programación. Debido a esto, en un lado positivo (desde mi punto de vista, por supuesto, bueno, los usuarios me apoyan), la interfaz del programa ha cambiado. Se han agregado muchos bloques interesantes. Se implementó la escala de esquemas y la búsqueda de bloques.

Pero aún así, el principal problema del proyecto sigue siendo que el desarrollador del programa es una persona (este soy yo), y el número de diferentes tarjetas controladoras, sensores, sensores, tarjetas de expansión fabricados por chinos y recientemente por nuestros fabricantes está en constante crecimiento. Y los usuarios quieren probarlos o usarlos en sus proyectos. Para dispositivos periféricos, en algún momento, este problema fue más o menos resuelto por mí con la ayuda de crear un editor de bloques personalizado. Este paso, como dicen, "disparó", y ahora, casi en la mayoría de las placas periféricas existentes, en Internet o en el foro del programa , puede encontrar el bloque de usuario correspondiente. Bueno, o en el mismo foro (o en un grupo en Vkontakte ) pida a los gurús locales que escriban uno. Por lo general, puede aceptar de una forma u otra.

Ahora es el momento de resolver el segundo problema: estas son placas controladoras.

Recientemente, se lanzó una versión beta del programa con el número 6.0. En esta versión, se implementa el editor para las descripciones de los usuarios de los controladores. Al igual que con los bloques personalizados, las descripciones pueden agruparse en bibliotecas, guardarse como descripciones separadas, así como bibliotecas completas como un archivo, y compartirse.

Con esta publicación, comienzo una serie de al menos dos publicaciones en las que consideraremos cómo usar este editor. En el primer artículo, con el permiso de shiotiny, intentaré describir su tablero ShIoTiny. En el segundo artículo, intentaremos llegar a un análogo de un controlador industrial real y describirlo.

Entonces comencemos.

Abra el programa FLProg. En el menú "Herramientas", seleccione el "Editor de descripciones personalizadas del controlador".



Se abre la ventana del editor de descripciones.

Las descripciones personalizadas se pueden combinar en la biblioteca con cualquier profundidad de anidamiento. Por lo tanto, primero creamos una biblioteca de descripción.



Establece el nombre de la biblioteca.



Después de eso crearemos una descripción del controlador en la biblioteca.



Y dale un nombre:



Al crear una descripción del controlador, llegamos inmediatamente a la rama de parámetros generales.



Aquí podemos cambiar el nombre, establecer el tipo de CPU, establecer el tamaño de la EEPROM, cambiar el número de versión de la descripción.

Como la placa ShloTiny se basa en el controlador ESP8266, la seleccionamos. Al elegir un controlador, el volumen EEPROM correspondiente se fija automáticamente. Si es necesario, este valor se puede cambiar. El número de versión predeterminado para la nueva descripción se establece en 1.

En el futuro, al cambiar las descripciones existentes, se recomienda cambiarlo en la dirección del aumento. Al usar esta descripción en un proyecto, el programa comparará la versión de la descripción en el proyecto y en la biblioteca. Si el número de versión de la descripción en la biblioteca es mayor que en el proyecto, el elemento para actualizar la descripción en el programa aparece en el menú "Proyecto" del programa. Si viceversa, aparecerá un elemento para actualizar la descripción en la biblioteca. Bueno, si la descripción del controlador utilizado en el proyecto no se encuentra en la biblioteca, el elemento para ingresar la descripción del proyecto en la biblioteca aparecerá en el mismo menú.

También en este hilo, puede escribir una descripción de texto del controlador que ayude con su selección.

Para aplicar los cambios realizados antes de cambiar a otra rama de los parámetros del controlador, haga clic en el botón "Aplicar". Si no se hace esto, los cambios no se guardarán.

Ahora considere el diagrama de circuito de la placa ShloTiny.



La placa tiene tres entradas digitales, tres salidas digitales, una entrada analógica y una entrada para el sensor. Un total de ocho conclusiones de la junta.

En el editor, vaya a la rama "Conclusiones del controlador" y establezca el número de conclusiones, no olvide hacer clic en el botón "Aplicar" después de eso.



El programa generará el número requerido de conclusiones. Pasamos al primero de ellos.



En esta rama, puede especificar un nombre de salida alternativo, que se mostrará en el programa. Si está ausente, el programa mostrará PinN donde N es el número de pin en la lista de pin. Le recomiendo que escriba una inscripción en la pizarra en el campo de nombre alternativo. Esto hará que sea más fácil entender qué conclusión se está sacando. Para la placa descrita, colocaremos allí el valor de Entrada1 de acuerdo con el diagrama del circuito. Entonces, en este hilo, puede escribir una descripción individual de la salida, por ejemplo, para indicar las características de su aplicación. Si es necesario, también puede especificar un alias para la salida, que se mostrará entre paréntesis en el programa después del nombre de la salida.

Después de hacer los cambios, no olvide hacer clic en el botón "Aplicar". Por el mismo principio, llamemos a las conclusiones restantes.



En la misma rama de los parámetros de salida principales, se le agregan las funciones que realiza.



Las siguientes funciones se pueden asignar a cada pin.



  • I2C es una función de uno de los pines del bus I2C (SDA o SCL).
  • SPI es una función de uno de los pines del bus SPI (MISO, MOSI, SCK, SS).
  • UART es una función de uno de los pines de la interfaz UART (RX o TX).
  • Función de entrada analógica
  • Función de salida analógica (aún no se utiliza en FLProg, retraso para el futuro).
  • Función de entrada / salida digital.

Asigne la función de entrada / salida digital del pin 1. Al asignar una nueva función (aún no configurada) a la salida, la rama "Errores" aparecerá en el árbol del controlador y toda la ruta a la rama de la función incorrecta se volverá roja. En la rama "Errores", puede ver una lista de errores encontrados en la descripción del controlador.



En este caso, la entrada 1 en la función "Entrada / salida digital" no especifica el número de esta entrada como digital. Cambiamos a la rama de esta función (en el futuro planeo hacer una transición directa a la rama deseada cuando hago clic en un error).



Según el diagrama del circuito de la placa, la salida "Entrada1" está conectada al pin GPIO2 del controlador. Ingresamos este valor en el campo "Número de entrada digital". Al compilar un proyecto, este valor se insertará en el código. Como no se proporciona el uso de esta entrada como salida, eliminamos la casilla de verificación "Se puede usar como salida". Como siempre, haga clic en el botón "Aplicar". Del mismo modo, configure las otras dos entradas digitales. Luego vaya a la salida de la entrada analógica "ADC1" y agregue la función "Entrada analógica".



En la configuración de esta función, debe especificar el número de esta salida como entrada analógica. Según el esquema, este es 0 (en ESP8266 es uno).



Luego vaya a la configuración de salida "1WIRE". Aquí le agregamos la función de entrada / salida digital, pero prohibimos su uso tanto de entrada como de salida. Como resultado, estará disponible para su selección solo en los bloques de sensores y no estará disponible al crear entradas y salidas.



Los ajustes de las salidas “K1” - “K3” son similares a los ajustes de las entradas “Entrada1” - “Entrada3” solo en el caso de las salidas, prohibimos que se utilicen como entrada.





Vaya a la rama "Imágenes". En él, podemos agregar imágenes cargadas en la descripción del controlador, por ejemplo, con la apariencia del controlador, pinout, etc.

Tenga en cuenta que las imágenes se cargan directamente en la descripción del controlador y se almacenan en un proyecto creado con él. Por lo tanto, no suba imágenes grandes. Esto implicará un aumento en el tamaño del proyecto y afectará la velocidad de su apertura.

La imagen se agrega mediante el botón "Agregar imagen".



Después de seleccionar y cargar una imagen (solo se admite el formato PNG), se crea una rama separada para cada imagen en el árbol. En esta rama, puede especificar un nombre para la imagen descargada, que se mostrará en la información del controlador.



Si es necesario, puede cargar varias imágenes y configurarlas en el orden deseado.





Pasamos a la rama "Bloques estándar".



Esta rama muestra los bloques que se pueden representar en la biblioteca de bloques estándar del programa de acuerdo con la configuración actual del programa. ¿Qué significa eso? Algunos de los componentes básicos del programa están destinados solo a ciertos tipos de CPU. Y su disponibilidad depende del procesador seleccionado. Además, los bloques diseñados para funcionar con SPI, I2C, UART aparecerán en esta lista solo si las funciones correspondientes se agregan a los pines del controlador. Los bloques diseñados para funcionar con la EEPROM aparecerán solo si el tamaño de la EEPROM especificado en la rama de los parámetros generales del controlador es mayor que cero, o si la función I2C se agrega a los pines del controlador. Por defecto, todos los bloques de la biblioteca están prohibidos para su uso (marcado en naranja). Puede permitir el uso de un bloque separado o de toda la carpeta de bloques resaltando la rama necesaria y haciendo clic en el botón "Permitir", o desde el menú contextual.



Cuando permite que se muestre un bloque o carpeta de bloques en el programa, se pintan de negro.

El bloqueo de un bloque o una carpeta separada está prohibido de la misma manera.



En una carpeta en la que no se pueden mostrar todos los bloques, están marcados con tres asteriscos antes y después del nombre.

Prohibimos el uso de motores, relojes en tiempo real, pantallas, unidades de control IR, sensores (excepto los sensores DS18B20 y DHT22, ya que el desarrollador de la placa hasta ahora solo ha anunciado su soporte), chips de expansión y un altavoz piezoeléctrico.



Haremos lo mismo para el lenguaje LAD



No olvides aplicarlos después de hacer cambios.

Las ramas restantes de la descripción del controlador se discutirán en la próxima publicación, mientras que la configuración actual es suficiente para usar esta placa en particular en el programa FLProg.

Por ahora, solo diré brevemente que la rama "Bloques especiales" se usa para cargar bloques personalizados en la descripción, que se mostrará en la biblioteca de bloques estándar en el programa cuando se usa este controlador. La rama "Código especial" se usa para registrar el código que siempre se insertará en el código compilado, y la rama "Bibliotecas especiales" se usa para cargar bibliotecas en la descripción del controlador, que se cargará en la carpeta \ bibliotecas ArduinoIDE con la que funciona el programa.

Después de todos los cambios, guarde la biblioteca de descripción del controlador.



Ahora intentemos usar la descripción del controlador que creamos.
En el programa FLProg, creamos un nuevo proyecto para el controlador.



Abra la ventana de selección del controlador.



Y seleccione la descripción que creamos.



Al elegir un controlador, puede ver sus imágenes y, si es necesario, guardar lo necesario en un archivo.





También puedes ver otros parámetros



Después de seleccionar el controlador, confirme su selección:



Como resultado, se abre la ventana principal de trabajo del proyecto, configurada de acuerdo con el controlador seleccionado.



El propósito de esta publicación no incluye la tarea de capacitación para trabajar con el programa FLProg. Esto está bastante bien descrito en mis publicaciones anteriores , en el sitio web del proyecto y en el foro del proyecto . Además, ya hay muchos canales en YouTube donde se publican videos tutoriales sobre cómo trabajar con el programa. Por ejemplo, un muy buen canal "Clave para Arduino" , justo ahora está llevando a cabo una serie de lecciones, con una muy buena presentación del material.

Por lo tanto, por ejemplo, simplemente creamos un proyecto simple e intentamos compilarlo.
Primero, agregue la entrada del controlador.



Solo las conclusiones que nos permitieron trabajar en esa capacidad están disponibles para su selección como entrada.



Luego cree una salida digital. Solo las conclusiones permitidas también están disponibles aquí.



Ensamblamos el circuito de modo que cuando se presiona el botón de la Entrada 1 (Entrada 1), se activa el relé K1 (Relé 1).
También extraemos la unidad para leer información del sensor DS18B20 en una placa de circuito en una placa separada.



Vaya a la configuración de bloque. Al crear el nuevo bus OneWire, vemos que todas las entradas / salidas digitales están disponibles para su selección. Esta es una falla en la versión 6.0. Pero dado que esta versión todavía tiene estado beta, es excusable. En la versión 6.1, será posible prohibir el uso de un pin como sensor, sensor o para chips de expansión. Además, en la próxima publicación te contaré otra forma de resolver este problema. Por ahora, seleccione 1WIRE pin.



Configuramos el sensor para establecer la dirección a través de la matriz.



Insertamos una nueva placa frente a la primera y extraemos el bloque "OneWire Bus Scan".



Lo configuramos en el mismo bus OneWire y en la misma matriz, en la que está configurada la unidad de lectura del sensor DS18B20.



Ensamblamos un esquema para un inicio único de una exploración de bus cuando se inicia el controlador, utilizando el bloque R del disparador (selección del borde de ataque).



En una placa con una unidad de lectura de datos del sensor DS18B20, ensamblamos un circuito de encendido / apagado de relé con histéresis. Para esto, utilizamos dos comparadores y un disparador SR. Gracias a este esquema, el relé 2 se encenderá cuando la temperatura baje a menos de 10 grados y se apagará cuando la temperatura suba a más de 20 grados.



Comenzamos el esquema de compilación.



Como resultado, el código resultante se abrirá en el IDE de Arduino. Como placa, seleccionamos NodeMCU, en el que se instala el mismo chip que en ShloTiny. Verificar el código muestra que es correcto y se puede descargar.



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; } 


Descripción del controlador ShloTiny para el programa FLProg

Terminaremos esta lección, en la próxima publicación trataremos de describir algo más serio y más cercano a los controladores industriales "reales".

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


All Articles