Paso 6: Código de Arduino
Para nuestro proyecto ejecutar tenemos que cargar el código para el Arduino para controlar los componentes eléctricos. Las bibliotecas están incluidas en el archivo zip siguiente y las carpetas en el interior se colocarán en la carpeta principal de la biblioteca de Arduino en su computadora después de descomprimir. Disponen de bibliotecas para el sensor infrarrojo, motor paso a paso y la visualización de siete segmentos. El archivo zip adjunto titulado PetFeeder contiene la carpeta con el sketch de Arduino necesario para ejecutar el código. Esto simplemente tiene que ser flasheado a la Arduino en orden para el código a ejecutar.
<br><p>#include <br>#include #include #include #include "SevSeg.h" SevSeg sevseg; #define STEPS_PER_MOTOR_REVOLUTION 32 #define STEPS_PER_OUTPUT_REVOLUTION 32 * 64 // Sets the motor for one revolution Stepper small_stepper(STEPS_PER_MOTOR_REVOLUTION, A1, A4, A2, A3); const int touchPin = A5; // Touch sensor assigned here int touchState; // Reading of the touch sensor int touched; // Condition if the touch sensor was pressed int disableTouch; // Disables multiple touches int feed; // Runs the feeding loop int AMorPM=LOW; // Decides if feeding cycle is in the morning or evening used for setting the time int justFed; // Condition used to set the time int minutes; // For the timer int i=0; // Used in formula for deciding if it's AM or PM int disableMinutes; // How long the touch sensor is disabled const int limPin = 8; // Limit sensor assigned here int limState = HIGH; // Limit state int pressed = LOW; // How many times the limit sensor was pressed int upright; int IRpin = A0; // pin for the IR sensor IRrecv irrecv(IRpin); decode_results results; int singlecup; int resetPin = 9;</p>
Esta inicializa las variables y establece ciertos Estados. Si estás comenzando el código en la noche, tienes que int AMorPM tan alto.
<br><p>void setup()<br>{ digitalWrite(resetPin, HIGH); delay(200); pinMode(limPin, INPUT); pinMode(touchPin, INPUT); pinMode(resetPin, OUTPUT); //Serial.begin(9600); Serial.println("reset");//print reset to know the program has been reset and byte numDigits = 4; byte digitPins[] = {10, 11, 12, 13}; //Set up for the 4 digit seven segment display byte segmentPins[] = {2, 3, 4, 5, 6, 7, 1, 14};</p><p> sevseg.begin(COMMON_CATHODE, numDigits, digitPins, segmentPins); sevseg.setBrightness(90); irrecv.enableIRIn(); // Start the receiver</p><p>}</p>
Esta configuración se ejecuta una vez y establece los pines como entradas o salidas. También configura el brillo de la pantalla de siete segmentos que se puede ajustar.
<br><p>void loop() {<br> static unsigned long startTime = millis(); static int minutes = 480; // Initializes for 480 minutes or 8 hours, since it is AM to begin with (9 am feeding -> 8 hours -> 5pm feeding) int justFed = LOW; touchState = digitalRead(touchPin); // Checks if touchpin was pressed limState = digitalRead(limPin); while(upright == LOW && limState == LOW){ // This loop does a one-time check to see if the cylinder is aligned, if not it will rotate until it's upright limState = digitalRead(limPin); small_stepper.setSpeed(380); small_stepper.step(10); if (limState == HIGH){ small_stepper.step(-60);</p><p> upright = HIGH; Serial.println("switch hit");</p><p> } }</p><p> if(touchState == LOW && disableTouch == LOW){ touched=HIGH; feed=HIGH; delay(10); // Serial.println("Pad was touched");</p><p> }</p>
Este es el comienzo del código principal. Comienza inicializando cuántos minutos hasta la próxima alimentación. Si tú vas a empezar en la noche y ha establecido AMorPM en alto, entonces también necesitará cambiar los minutos aquí a 960 (o 16 horas hasta la próxima alimentación). Esto también hace una comprobación inicial para asegurarse de que el cilindro esté en posición vertical al girar el sistema en que el cilindro gire hasta que el interruptor es golpeado. La parte inferior del código establece que si la capacitancia del sensor táctil va baja (es decir, le apreté) entonces establece el lazo de alimentación alta, y el táctil se desactivará para evitar alimentaciones múltiples.
<p>if (irrecv.decode(&results)) {//has a transmission been received?<br> Serial.println(results.value);//If yes: interpret the received commands... if (results.value == 3810010651){ feed = HIGH; touched = HIGH; } //Mark's refresh button 5316027 //Joe's - digital zoom button if (results.value == 2885434849){ disableTouch = LOW; } if (results.value == 810318687){ Serial.println("resetting"); delay(10); digitalWrite(resetPin, LOW); Serial.println("this never happens"); } // Mark's one button 2534850111 //Joe's timer on button if (results.value == 1429432985){ small_stepper.setSpeed(300); small_stepper.step(2000); pressed = LOW; delay(3000); // Initially has a large step to get off the limiting sensor (any less and the sensor registers multiple presses) while(pressed == LOW){ small_stepper.setSpeed(450); // This loop continues until the limiting sensor is pressed once (meaning the cylinder went around once for one cup) small_stepper.step(30); delay(200); // It will move forward 50 steps and back 20, to minimize jamming small_stepper.step(-10); limState = digitalRead(limPin); if (limState == HIGH){ pressed = HIGH; // Reads the limit pin and counts a press Serial.println("switch hit"); delay(4500); } } small_stepper.setSpeed(500); small_stepper.step(-20); delay(10); small_stepper.setSpeed(500); small_stepper.step(-50); delay(500); small_stepper.setSpeed(500); small_stepper.step(50); delay(500); small_stepper.setSpeed(500); small_stepper.step(-50); delay(500); small_stepper.setSpeed(500); small_stepper.step(50); delay(500); small_stepper.setSpeed(500); small_stepper.step(-50); delay(500); small_stepper.setSpeed(500); small_stepper.step(50); delay(500); small_stepper.setSpeed(500); small_stepper.step(-50); delay(500); small_stepper.setSpeed(500); small_stepper.step(50); delay(500); small_stepper.setSpeed(500); small_stepper.step(-50); delay(500); small_stepper.setSpeed(500); small_stepper.step(50); delay(500); small_stepper.setSpeed(500); small_stepper.step(-50); delay(500); small_stepper.setSpeed(500); small_stepper.step(50); delay(500); small_stepper.setSpeed(500); small_stepper.step(-50); delay(500); small_stepper.setSpeed(500); small_stepper.step(50); delay(500); small_stepper.setSpeed(500); small_stepper.step(-50); delay(500); small_stepper.setSpeed(500); small_stepper.step(50); delay(500); small_stepper.setSpeed(500); small_stepper.step(-50); delay(500); small_stepper.setSpeed(500); small_stepper.step(50); delay(500); small_stepper.setSpeed(500); small_stepper.step(-50); delay(500); small_stepper.step(50); delay(500); pressed = LOW; }</p><p> irrecv.resume(); // Receive the next value }</p>
Este código se corresponde con los mandos a distancia. Estos números se sustituirá por los valores que recibió de la IRdecoder. Hay una función para ejecutar un ciclo de alimentación, funcionando una taza extra (para días donde crees que tu mascota necesita las calorías extras) y una función para reiniciar todo el sistema.
<p>if(feed == HIGH){ //Feeds Lydia<br> small_stepper.setSpeed(300); small_stepper.step(2000); pressed = LOW; delay(3000); // Initially has a large step to get off the limiting sensor (any less and the sensor registers multiple presses) while(pressed == LOW){ small_stepper.setSpeed(450); // This loop continues until the limiting sensor is pressed once (meaning the cylinder went around once for one cup) small_stepper.step(30); delay(200); // It will move forward 50 steps and back 20, to minimize jamming small_stepper.step(-10); limState = digitalRead(limPin); if (limState == HIGH){ pressed = HIGH; // Reads the limit pin and counts a press Serial.println("switch hit"); delay(4500); } }</p><p> small_stepper.setSpeed(500); small_stepper.step(-20); delay(10); small_stepper.setSpeed(500); small_stepper.step(-50); delay(500); small_stepper.setSpeed(500); small_stepper.step(50); delay(500); small_stepper.setSpeed(500); small_stepper.step(-50); delay(500); small_stepper.setSpeed(500); small_stepper.step(50); delay(500); small_stepper.setSpeed(500); small_stepper.step(-50); delay(500); small_stepper.setSpeed(500); small_stepper.step(50); delay(500); small_stepper.setSpeed(500); small_stepper.step(-50); delay(500); small_stepper.setSpeed(500); small_stepper.step(50); delay(500); small_stepper.setSpeed(500); small_stepper.step(-50); delay(500); small_stepper.setSpeed(500); small_stepper.step(50); delay(500); small_stepper.setSpeed(500); small_stepper.step(-50); delay(500); small_stepper.setSpeed(500); small_stepper.step(50); delay(500); small_stepper.setSpeed(500); small_stepper.step(-50); delay(500); small_stepper.setSpeed(500); small_stepper.step(50); delay(500); small_stepper.setSpeed(500); small_stepper.step(-50); delay(500); small_stepper.setSpeed(500); small_stepper.step(50); delay(500); small_stepper.setSpeed(500); small_stepper.step(-50); delay(500); small_stepper.setSpeed(500); small_stepper.step(50); delay(500); small_stepper.setSpeed(500); small_stepper.step(-50); delay(500); small_stepper.step(50); delay(500); small_stepper.setSpeed(300); small_stepper.step(2000); delay(3000); pressed = LOW; while(pressed == LOW){</p><p> small_stepper.setSpeed(450); small_stepper.step(30); delay(200); small_stepper.step(-10); limState = digitalRead(limPin); if (limState == HIGH){ pressed = HIGH; delay(500); //Serial.println("Pad was touched"); Serial.println("switch hit");</p><p> } } small_stepper.setSpeed(500); small_stepper.step(-25); delay(500); small_stepper.setSpeed(500); small_stepper.step(-50); delay(500); small_stepper.setSpeed(500); small_stepper.step(50); delay(500); small_stepper.setSpeed(500); small_stepper.step(-50); delay(500); small_stepper.setSpeed(500); small_stepper.step(50); delay(500); small_stepper.setSpeed(500); small_stepper.step(-50); delay(500); small_stepper.setSpeed(500); small_stepper.step(50); delay(500); small_stepper.setSpeed(500); small_stepper.step(-50); delay(500); small_stepper.setSpeed(500); small_stepper.step(50); delay(500); small_stepper.setSpeed(500); small_stepper.step(-50); delay(500); small_stepper.setSpeed(500); small_stepper.step(50); delay(500); small_stepper.setSpeed(500); small_stepper.step(-50); delay(500); small_stepper.setSpeed(500); small_stepper.step(50); delay(500); small_stepper.setSpeed(500); small_stepper.step(-50); delay(500); small_stepper.setSpeed(500); small_stepper.step(50); delay(500); small_stepper.setSpeed(500); small_stepper.step(-50); delay(500); small_stepper.setSpeed(500); small_stepper.step(50); delay(500); small_stepper.setSpeed(500); small_stepper.step(-50); delay(500); small_stepper.setSpeed(500); small_stepper.step(50); delay(500); small_stepper.setSpeed(500); small_stepper.step(-50); small_stepper.setSpeed(500); small_stepper.step(50); delay(500); pressed = LOW; feed = LOW; i = i + 1; // Tells the feeder it's moving on to the next cycle (AMorPM) justFed = HIGH; }</p>
Esta es la parte más importante del código - el ciclo de alimentación. Comienza por tomar un gran "paso" para mover la mayor parte del camino alrededor del sistema. Él entonces juegos presionados a la baja, que corresponde a la limitación del interruptor. Si no lo hace todo el camino alrededor entonces allí fue un atasco, para que se ejecute a través de un bucle de tiempo sin interferencia. Empezará a tomar 30 pasos hacia delante y 10 pasos atrás hasta el interruptor limitador que golpeó. Una vez arriba, se moverá hacia adelante y hacia atrás ayudar a agitar comida en el cilindro. Este ciclo comenzará otra vez, para alimentar a mi mascota un total de dos tazas. Esto se puede ajustar para su mascota mediante la eliminación del segundo ciclo.
<p>if(disableTouch == HIGH && minutes == 960 && AMorPM == HIGH){ // If the touch sensor is ever pressed, it becomes disabled. This will allow it to be pressed again once a new feeding cycle has begun.<br> disableTouch = LOW; } if(disableTouch == HIGH && minutes == 480 && AMorPM == LOW){ disableTouch = LOW; }</p>
Si se presiona el sensor de contacto para una alimentación temprana, se activa la función de disableTouch. Yo llamo a esto mi "característica de prueba de Greg". Tengo un amigo llamado a Greg que, sé, pasaba el tiempo pulsando el sensor de contacto una y otra vez hasta que todos de 20 libras de comida para perros esparcidos por todo mi piso. El sensor de contacto se activará otra vez una vez transcurrido el tiempo de alimentación temprana, y vuelve a es programación regular.
<p>if (millis() >= startTime) {<br> minutes--; // 60000 seconds is equal to 1 min startTime += 60000; if (minutes == 0) { // Runs the feeding cycle if the timer reaches zero feed = HIGH; disableTouch=LOW; touched = LOW; } sevseg.setNumber(minutes, 1); }</p>
Esta función si es la función del temporizador. Le cuenta minuto a minuto, y si los minutos igualan a cero, se ejecuta la función de alimentación y desactivar la función de prueba de Greg.
<p>if(i%2 == 1){ // Conditional statement to decide if it is AM or PM odd cycles a re PM<br> AMorPM = HIGH; } else if(i%2 == 0){ AMorPM=LOW;}</p>
Esta es la parte del código que cambia entre los dos ciclos de alimentación. Cada vez que el ciclo de alimentación funciona "i" se incrementará en uno. Esto indica que cuando "i" se divide por y y tiene un resultado (impar), pasará al ciclo de alimentación de la noche y viceversa. Esto se correlaciona a restablecer el temporizador.
<p>if(justFed == HIGH && touched == LOW && AMorPM == LOW){ // Conditions for setting the time and disabling the touch sensor.<br> minutes = 480; justFed = LOW; } else if(justFed == HIGH && touched == LOW && AMorPM == HIGH){ minutes = 960; justFed = LOW; } else if(justFed == HIGH && touched == HIGH && AMorPM == LOW){ minutes = 480 + minutes; justFed = LOW; disableTouch = HIGH;</p><p>sevseg.refreshDisplay();</p><p> } else if(justFed == HIGH && touched == HIGH && AMorPM == HIGH){ minutes = 960 + minutes; justFed = LOW; disableTouch = HIGH;</p><p>sevseg.refreshDisplay();</p><p>} sevseg.refreshDisplay(); // Must run repeatedly }</p>
Este es el final del código que restablece el temporizador en el momento adecuado. Si se pulsa el sensor de contacto, se toma el tiempo que quedaba y añadir a la próxima vez alimentación. Esto es así el alimentador es nunca fuera de horario. Si el temporizador funciona a cero, simplemente se establecerá el tiempo para la próxima vez alimentación. La sevseg.refreshDisplay(); es lo que dice el contador de tiempo para actualizar.