/** * Vending machine with cookies * * Author: Jan Dvořák z Vozerovic * E-mail: dvorkaman@gmail.com * Web: dvorkaman.asp2.cz * Created: 2015 - 2016 */ /* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // INCLUDES #include "main.h" #include "dvorkaman.c" /* MAP */ /* MOTOR 1: MOTOR 2: Belt MOTOR 3: MOTOR 4: SERVO 1: Up SERVO 2: Down SERVO 3: Coin SERVO 4: Door LIGHT 1: GREEN - OK LIGHT 2: RED - WAIT LIGHT 3: LIGHT 4: !! PC 10 and 11 used for PRINTER USART */ libF4Mini f4mini; libMatrixSwitch inputs; uint16_t input_in[] = { GPIO_Pin_0, GPIO_Pin_1, GPIO_Pin_2, GPIO_Pin_4 }; uint16_t input_out[] = { GPIO_Pin_0, GPIO_Pin_1, GPIO_Pin_2 }; bool enableRead; bool readNext; bool lastGreen, greenOn; // TRUE if COIN, FALSE if belt moved bool coinInserted; uint8_t selectedBelt, lastMovedBelt; uint8_t cookiesBought; uint8_t cookiesBoughtIndexes[8]; uint8_t cookies[4][PRINTER_COLUMNS + 1] = { { 'C', 'o', 'k', 'e', 't', 'k', 'a', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '1', '0', ',', '-', '\0' }, { 'P', 'e', 'a', 'n', 'u', 't', '&', 'c', 'h', 'o', 'c', 'o', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '1', '0', ',', '-', '\0' }, { 'M', 'i', 'l', 'k', 'y', 'W', 'a', 'y', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '1', '0', ',', '-', '\0' }, { 'F', 'i', 'd', 'o', 'r', 'k', 'a', ' ', 'k', 'o', 'k', 'o', 's', 'o', 'v', 'a', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '1', '0', ',', '-', '\0' }, }; libAnalogToDigital irSensor; libPrinter printer; // MAIN int main(void) { system_initialize(3); // A..C systemTime_initialize(); F4Mini_initialize( // !! PC 10 and 11 used for PRINTER USART &f4mini, XBEE_API_COORD_MSB, XBEE_API_COORD_LSB, // coordinator xbee addresses (me is slave) io_adc, // A0..A3 type libPin_OPEN_DRAIN, // A0 - [1, 4, 7, *] - OUTPUT [3] libPin_OPEN_DRAIN, // A1 - [2, 5, 8, 0] [1] libPin_OPEN_DRAIN, // A2 - [3, 6, 9, #] [5] libPin_ANALOG, // A3 - IR input libPin_OUTPUT, // A8 libPin_OUTPUT, // B12 libPin_OUTPUT, // B13 libPin_INPUT_UP, // C0 - [1, 2, 3] - INPUT [2] libPin_INPUT_UP, // C1 - [4, 5, 6] [7] libPin_INPUT_UP, // C2 - [7, 8, 9] [6] libPin_INPUT_UP, // C4 - [*, 0, #] [4] libPin_OUTPUT, // C5 libPin_OUTPUT // C9 ); initializePeripherals(); //Main loop while (1) { readInputs(); setLights(); // Analog if (analogFilter_isReady(&f4mini.af) == TRUE) { evaluateIrSensor(analogToDigital_read(&irSensor)); analogFilter_clear(&f4mini.af); } } } // READ void readInputs(void) { uint32_t in; if (enableRead == FALSE) { return; } in = matrixSwitch_read(&inputs); if (in > 0 && readNext == FALSE) { return; } // must be pressed zero before next read // process value if (in == 0) { readNext = TRUE; return; } // non - zero value readNext = FALSE; if ((in & 0x0001) > 0 && coinInserted == TRUE) // Key 1 - up left { selectBelt(1); moveBelt(1); return; } if ((in & 0x0100) > 0 && coinInserted == TRUE) // Key 3 - up right { selectBelt(2); moveBelt(2); return; } if ((in & 0x0004) > 0 && coinInserted == TRUE) // Key 7 - down left { selectBelt(3); moveBelt(3); return; } if ((in & 0x0400) > 0 && coinInserted == TRUE) // Key 9 - down right { selectBelt(4); moveBelt(4); return; } // ---------------------------------------- if ((in & 0x0008) > 0) // Key * - start belt, servo MIN { pwmServo_setPosition(&f4mini.servo3, COIN_MIN); pwmServo_setPosition(&f4mini.servo4, DOOR_MIN); if (selectedBelt == 0) { motor_runForwardsPercent(&f4mini.motor2, BELT_SPEED); } else { runMotor(selectedBelt); } return; } if ((in & 0x0800) > 0) // Key # - stop belt, servo MAX { pwmServo_setPosition(&f4mini.servo3, COIN_MAX); pwmServo_setPosition(&f4mini.servo4, DOOR_MAX); motor_stop(&f4mini.motor2); return; } // ---------------------------------------- if ((in & 0x0010) > 0) // Key 2 - printer test { printer_writeln(&printer, "Printer test"); return; } if ((in & 0x0020) > 0) // Key 5 - emg stop { clearPeripherals(); return; } // ---------------------------------------- if ((in & 0x0080) > 0 && cookiesBought > 0 && coinInserted == FALSE) // Key 0 - Print bill { finishOrder(); return; } // ---------------------------------------- } // SELECT BELT void selectBelt(uint8_t number) { // 0 = none; 1 = left top, 2 = right top; 3 = left botom, 4 = right bottom selectedBelt = number; switch (number) { case 0: pwmServo_setPosition(&f4mini.servo1, UP_MID); pwmServo_setPosition(&f4mini.servo2, DOWN_MID); break; case 1: pwmServo_setPosition(&f4mini.servo1, UP_MAX); pwmServo_setPosition(&f4mini.servo2, DOWN_MID); break; case 2: pwmServo_setPosition(&f4mini.servo1, UP_MIN); pwmServo_setPosition(&f4mini.servo2, DOWN_MID); break; case 3: pwmServo_setPosition(&f4mini.servo1, UP_MID); pwmServo_setPosition(&f4mini.servo2, DOWN_MIN); break; case 4: pwmServo_setPosition(&f4mini.servo1, UP_MID); pwmServo_setPosition(&f4mini.servo2, DOWN_MAX); break; } } // INIT void initializePeripherals() { matrixSwitch_initialize(&inputs, GPIOC, &input_in[0], 4, GPIOA, &input_out[0], 3); printer_initialize(&printer, USART3); // IR analogToDigital_initializeAnalogFilter(&irSensor, &f4mini.af, 0); // Turn on lights for a moment gpioPin_write(&f4mini.light1, Bit_SET); gpioPin_write(&f4mini.light2, Bit_SET); gpioPin_write(&f4mini.light3, Bit_SET); gpioPin_write(&f4mini.light4, Bit_SET); systemTime_delayMs(1000); clearPeripherals(); } // CLEAR void clearPeripherals() { F4Mini_clearPerihperals(&f4mini); selectBelt(0); enableRead = TRUE; readNext = TRUE; lastGreen = TRUE; // force change greenOn = FALSE; lastMovedBelt = 0; cookiesBought = 0; coinInserted = FALSE; pwmServo_setPosition(&f4mini.servo3, COIN_MAX); pwmServo_setPosition(&f4mini.servo4, DOOR_MAX); } // RUN MOTOR FOR BELT void runMotor(uint8_t beltNumber) { motor_stop(&f4mini.motor2); // always // Down - FW if (beltNumber == 3 || beltNumber == 4) { motor_runForwardsPercent(&f4mini.motor2, BELT_SPEED); } // Up - BW if (beltNumber == 1 || beltNumber == 2) { motor_runBackwardsPercent(&f4mini.motor2, BELT_SPEED); } } // MOVE BELT void moveBelt(uint8_t beltNumber) { // Disable read, show lights state enableRead = FALSE; greenOn = FALSE; // red LED setLights(); systemTime_delayMs(SERVO_MOVE_TIME); runMotor(beltNumber); systemTime_delayMs(beltNumber == lastMovedBelt ? BELT_SAME_MOVE_TIME : BELT_MOVE_TIME); lastMovedBelt = beltNumber; runMotor(0); // stop // Enable input enableRead = TRUE; cookiesBoughtIndexes[cookiesBought] = beltNumber - 1; // one based cookiesBought = cookiesBought + 1; // Enable coin, clear inserted flag pwmServo_setPosition(&f4mini.servo3, COIN_MAX); // open coin coinInserted = FALSE; } // SET LIGHTS void setLights() { if (lastGreen != greenOn) { lastGreen = greenOn; gpioPin_write(&f4mini.light1, greenOn ? Bit_SET : Bit_RESET); // green gpioPin_write(&f4mini.light2, greenOn ? Bit_RESET : Bit_SET); // red } } // IR sensor void evaluateIrSensor(BitAction value) { if (coinInserted == TRUE) { return; } // Coin inserted if (value == Bit_SET) { coinInserted = TRUE; // Set lights greenOn = TRUE; setLights(); // Move servo pwmServo_setPosition(&f4mini.servo3, COIN_MIN); // close coin } } // FINISH ORDER void finishOrder(void) { uint8_t i, c; uint8_t price[3] = { '0', '0', '\0' }; pwmServo_setPosition(&f4mini.servo4, DOOR_MIN); price[0] = '0' + cookiesBought; // Header printer_writeBitmap(&printer, 384, 52, (uint8_t *)&dvorkaman[0]); printer_feedLines(&printer, 1); // Goods for (i = 0; i < cookiesBought; i++) { c = cookiesBoughtIndexes[i]; printer_writeln(&printer, &cookies[c][0]); } // Footer printer_writeln(&printer, "--------------------------------"); printer_write(&printer, "Total: "); printer_write(&printer, &price[0]); printer_writeln(&printer, ",-"); printer_feedLines(&printer, 6); systemTime_delayMs(1500); pwmServo_setPosition(&f4mini.servo4, DOOR_MAX); cookiesBought = 0; }