MT04 - Introducción a electrónica y programación¶

En este módulo técnico toca trabajar con electrónica y programación, concretamente trabajaremos con la placa Arduino, concretamente con la placa Arduino UNO. Para programar el microcontrolador utilizaremos el IDE de Arduino o el Arduino Cloud editor. También nos apoyaremos en simuladores tales cómo Tinkercad, Wokwi o Fritzing.
El desafío consta de lo siguiente:
- LEER MÍNIMO DOS INPUTS
- ACTUAR MÍNIMO DOS OUTPUTS
En mi caso optaré por orientar esta práctica a una posible aplicación en el proyecto final, concretamente, controlar un extrusor de impresora 3D con la placa Arduino UNO. Tomaré como entradas una sonda PT100 y un potenciómetro, mientras que las salidas serán un hotend de 20w y un motor de pasos Nema 17.
01.¶
Lo primero fue entender cómo funciona la sonda PT100 de dos hilos, podemos decir que esta sonda funciona como una resistencia variable que aumenta su resistencia en función al aumento de temperatura. Esta sonda fue recuperada de un printcore de Ultimaker 3 roto por lo que un buen inicio es buscar información sobre la electrónica asociada a estos componentes. De la búsqueda de material pudimos obtener un indicio entre los archivos dispuestos en los repositorios github de Ultimaker. Desde aquí logramos calcular algunos valores teóricos de los voltajes deberíamos leer en el arduino y saber a qué temperatura corresponde ese valor, podríamos decir que debemos caracterizar el comportamiento del sensor.

El código para esta prueba se basó en el siguiente sketch. Con una pendiente teórica del 1.94 corrimos el siguiente código y obtuvimos lecturas muy convincentes.

const int analogInPin = A0; // Analog input pin that the potentiometer is attached to
const int analogOutPin = 9; // Analog output pin that the LED is attached to
float m = 0.0;
float tempF=0.0;
int sensorValue = 0; // value read from the pot
long int sensorValue1 = 410.0 ;
long int sensorValue2 = 668.0;
int temperatura1 = 0;
int temperatura2 = 500;
int offset = 25;
String inString = "";
int outputValue = 0; // value output to the PWM (analog out)
int SerialComando = 0;
void setup() {
Serial.begin(9600);
calibracionProceso();
}
void loop() {
sensorValue = analogRead(analogInPin);
Serial.print("Sensor PT100 = ");
Serial.print(sensorValue);
Serial.print("\t Temperatura = ");
tempF=(float)(m*(sensorValue-sensorValue2)+temperatura2-offset);
Serial.print(tempF);
Serial.println("°C"); delay(100);
}
void calibracionProceso() {
Serial.print("La pendiente del sistema es m=(y2-y1)/(x2-x1)=");
m = (float)((temperatura1 - temperatura2)/((float)sensorValue1 - (float)sensorValue2));
Serial.println(m);
}
02.¶
En este siguiente paso deberemos relacionar la entrada y la salida, la sonda PT100 y el hotend. Para ello deberemos implementar un sistema de control que mantenga estable la temperatura elegida, esto lo logramos implementando un sistema de control cerrado, con una retroalimentación y lo mejor, controlar la temperatura mediante un PID. El nombre PID proviene de sus tres componentes principales: Proporcional (P), Integral (I) y Derivativo (D). El controlador PID funciona leyendo un sensor, calculando la salida deseada del actuador y luego ajustando la salida del actuador en función del error entre la salida deseada y la medida actual.
El sketch se basa en un ejemplo proporcionado en la librería creada por RobTillaart. En la misma basta con configurar los pines de entrada y salida. Para hallar los valores de las constanses PID existen algunas técnicas para calcular valores teóricos, en este caso se probaron algunos valores aleatorios y se procedió a ajustarlos hasta obtener un rendimiento aceptable.
#include "PID_RT.h"
PID_RT PID;
const int PWM_PIN = 3; // UNO PWM pin
int op = 0;
float input = 0;
const int analogInPin = A0; // Analog input pin that the potentiometer is attached to
const int analogOutPin = 9; // Analog output pin that the LED is attached to
float m = 0.0;
float tempF=0.0;
int sensorValue = 0; // value read from the pot
long int sensorValue1 = 410.0 ;
long int sensorValue2 = 668.0;
int temperatura1 = 0;
int temperatura2 = 500;
int offset = 25;
String inString = "";
int outputValue = 0; // value output to the PWM (analog out)
int SerialComando = 0;
void setup() {
Serial.begin(9600);
PID.setPoint(100);
PID.setOutputRange(0, 255); // PWM range
PID.setInterval(50);
PID.setK(10, 1, 15);
PID.start();
calibracionProceso();
}
void loop() {
sensorValue = analogRead(analogInPin);
Serial.print("Sensor PT100 = ");
Serial.print(sensorValue);
Serial.print("\t Temperatura = ");
tempF=(float)(m*(sensorValue-sensorValue2)+temperatura2-offset);
Serial.print(tempF);
Serial.println("°C");
input = tempF;
// input = analogRead(A0);
if (PID.compute(input))
{
op = PID.getOutput();
analogWrite(PWM_PIN, op);
Serial.print(" op: ");
Serial.print(op);
Serial.print(" ");
}
}
void calibracionProceso() {
Serial.print("La pendiente del sistema es m=(y2-y1)/(x2-x1)=");
m = (float)((temperatura1 - temperatura2)/((float)sensorValue1 - (float)sensorValue2));
Serial.println(m);
}
03.¶
En este punto sumaremos una nueva entrada al circuito, el potenciómetro. Para la conexión conectaremos los pines de afuera a 5v y gnd mientras que el del medio lo conectaremos a la entrada analógica A1 para obtener una lectura entre 0 y 1023. A nivel de código solo basta con agregar en el loop un analogRead(); para obtener la lectura, adicionalmente podemos crear una variable para almacenar la lectura y luego poderla mostrar en pantalla mediante el monitor serial.
En la siguiente gráfica obtenida del ploteo de las variables en el serial plotter podemos apreciar el rango de variación de la entrada analógica que cambia a la par de la resistencia del potenciómetro (señal color naranja), la señal de color negro es el valor equivalente a loa 100°C de la medida de la sonda PT100 y también se puede ver en color rojo la señal del pwm generada por el PID para estabilizar la temperatura.

04.¶
Ahora solo resta poder controlar el motor de pasos Nema 17 para tener todos los componentes necesarios para crear un extrusor controlado por arduino, este sería nuestra segunda salida controlada y con esta estaría completa la consigna. Para poder controlar el motor de pasos vamos a necesitar controlar el driver encargado de excitar las bobinas del motor con el voltaje de trabajo de estos motores pero recibiendo las señales de control de 5v desde el arduino. El driver a utilizar es el A4988.
El código implementado se basó en el tutorial de yomaker y quedó de la siguiente manera.
int steps = 5; // pin step 5
int direccion = 4; // pin direccion 4
int potenciometro; // lectura del potenciometro
void setup() {
// inicializamos pin como salidas.
pinMode(steps, OUTPUT);
pinMode(direccion, OUTPUT);
}
void loop() {
digitalWrite(direccion, HIGH); // cambiamos de dirección segun pulsador
potenciometro = analogRead(A2); // leemos el potenciometro
potenciometro = map(potenciometro,0,1024,900,2500); // adaptamos el valor leido a un retardo
digitalWrite(steps, HIGH); // Aqui generamos un flanco de bajada HIGH - LOW
delayMicroseconds(5); // Pequeño retardo para formar el pulso en STEP
digitalWrite(steps, LOW); // y el A4988 de avanzara un paso el motor
delayMicroseconds(potenciometro); // generamos un retardo con el valor leido del potenciometro
}
05. La unificación¶
Bueno, después de dar unas buenas vueltas al asunto, he intentado unificar el sistema de control de temperatura y el control de motor con potenciómetro fracasando con total éxito.
Lo que entiendo que sucede es un conflicto de tiempos de ejecución, ya que cada sketch por separado funciona bien pero al unificarlos el PID pierde precisión y el motor de pasos se comporta de manera errónea. Para solucionar este inconveniente intenté implementar FreeRTOS, este es un sistema operativo de tiempo real kernel para dispositivos embebidos que puede correr en un microcontrolador. Aquí logramos switchear entre ambas tareas y asignarles prioridades.
#include "PID_RT.h"
PID_RT PID;
const int PWM_PIN = 3; // UNO PWM pin
int op = 0;
float input = 0;
const int analogInPin = A0; // Analog input pin that the potentiometer is attached to
const int analogOutPin = 9; // Analog output pin that the LED is attached to
float m = 0.0;
float tempF = 0.0;
int sensorValue = 0; // value read from the pot
long int sensorValue1 = 410.0 ;
long int sensorValue2 = 668.0;
int temperatura1 = 0;
int temperatura2 = 500;
int offset = 25;
String inString = "";
int outputValue = 0; // value output to the PWM (analog out)
int SerialComando = 0;
void setup() {
Serial.begin(9600);
PID.setPoint(100);
PID.setOutputRange(0, 255); // PWM range
PID.setInterval(50);
PID.setK(10, 1, 15);
PID.start();
calibracionProceso();
}
void loop() {
sensorValue = analogRead(analogInPin);
Serial.print("Sensor PT100 = ");
Serial.print(sensorValue);
Serial.print("\t Temperatura = ");
tempF = (float)(m * (sensorValue - sensorValue2) + temperatura2 - offset);
Serial.print(tempF);
Serial.println("°C");
input = tempF;
// input = analogRead(A0);
if (PID.compute(input))
{
op = PID.getOutput();
analogWrite(PWM_PIN, op);
Serial.print(" op: ");
Serial.print(op);
Serial.print(" ");
}
Serial.print(" Potenciómetro: ");
Serial.print(lectura_pote);
Serial.print(" ");
}
void calibracionProceso() {
Serial.print("La pendiente del sistema es m=(y2-y1)/(x2-x1)=");
m = (float)((temperatura1 - temperatura2) / ((float)sensorValue1 - (float)sensorValue2));
Serial.println(m);
}
El resultado no fue muy convincente, solo funciona una de las dos tareas cuando le damos la máxima prioridad. Me toca seguir investigando alternativas para poder implementar un control más robusto para el extrusor.
Enlace a archivos descargables
Haz clic en el siguiente enlace para visitar el sitio:
Archivos descargables del Módulo