Loop based controller for dual lane siemens siplace feeder.

Dependencies:   USBDevice mbed

Files at this revision

API Documentation at this revision

Comitter:
Issus
Date:
Thu Feb 02 19:18:12 2017 +0000
Child:
1:4d3738338cf1
Commit message:
Initial

Changed in this revision

HBridge.cpp Show annotated file Show diff for this revision Revisions of this file
HBridge.h Show annotated file Show diff for this revision Revisions of this file
USBDevice.lib Show annotated file Show diff for this revision Revisions of this file
feederController.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HBridge.cpp	Thu Feb 02 19:18:12 2017 +0000
@@ -0,0 +1,32 @@
+#include "mbed.h"
+#include "HBridge.h"
+
+HBridge::HBridge(PinName i1, PinName i2):
+    IN1(i1), IN2(i2)
+{
+}
+
+
+void HBridge::Coast()
+{
+    IN1 = 0;
+    IN2 = 0;
+}
+
+void HBridge::Forward()
+{
+    IN1 = 1;
+    IN2 = 0;
+}
+
+void HBridge::Reverse()
+{
+    IN1 = 0;
+    IN2 = 1;
+}
+
+void HBridge::Brake()
+{
+    IN1 = 1;
+    IN2 = 1;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HBridge.h	Thu Feb 02 19:18:12 2017 +0000
@@ -0,0 +1,20 @@
+#ifndef HBRIDGE_H_
+#define HBRIDGE_H_
+
+#include "mbed.h"
+
+class HBridge 
+{
+    public:
+        HBridge(PinName i1, PinName i2);
+        void Coast();
+        void Brake();
+        void Forward();
+        void Reverse();
+    
+    private:
+        DigitalOut IN1;
+        DigitalOut IN2;
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice.lib	Thu Feb 02 19:18:12 2017 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/USBDevice/#01321bd6ff89
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/feederController.cpp	Thu Feb 02 19:18:12 2017 +0000
@@ -0,0 +1,708 @@
+#include "mbed.h"
+#include "USBSerial.h"
+#include "HBridge.h"
+
+extern "C" void mbed_mac_address(char *);
+
+/************
+TODO LIST:
+*************
+* Move defs to .h file
+* Move tape pickup into main loop. Interrupts on it dont seem to be entirely reliable (spurrious)
+* printf needs to be replace with a function that putc instead for non-formatted strings
+* Convert lanes to a class so they there isn't duplicate code
+*************/
+
+// HARDWARE PIN DEFS
+#define PIN_LED             P0_7
+#define PIN_VINREF          P0_23
+
+#define PIN_LED_YELLOW_0    P0_9
+#define PIN_LED_YELLOW_1    P1_13
+
+#define PIN_BTN_GREEN_0     P0_22
+#define PIN_BTN_GREEN_1     P1_14
+
+#define PIN_BOARD_FEED      P0_1
+
+#define PIN_GATE_0          P0_11
+#define PIN_GATE_1          P0_12
+#define PIN_GATE_2          P0_13
+#define PIN_GATE_3          P0_14
+
+#define PIN_LANECTL_0       P0_16
+#define PIN_LANECTL_1       P1_15
+
+#define PIN_RS485_DIR       P0_17
+#define PIN_UART_TXD        P0_18
+#define PIN_UART_RXD        P0_19
+
+#define PIN_SOLCTL_0        P1_19
+#define PIN_SOLCTL_1        P1_25
+
+#define PIN_BTN_LED_0       P1_29
+#define PIN_BTN_LED_1       P1_22
+
+#define PIN_H1_IN1          P0_20
+#define PIN_H1_IN2          P0_2
+#define PIN_H1_IN3          P1_26
+#define PIN_H1_IN4          P1_27
+
+#define PIN_H2_IN1          P1_28
+#define PIN_H2_IN2          P1_31
+#define PIN_H2_IN3          P0_8
+#define PIN_H2_IN4          P1_21
+
+
+// SETTINGS
+#define TAPE_MAX_PULL_TIME 2 // seconds
+
+#define FEED_FWD_ENC_PULSE 2 // actually this + 1
+// encoder pulses: >(lane0FeedDistance * FEED_FWD_ENC_PULSE)
+// 3 for 1 position, 5 for 2 positions
+
+
+/*****************************************************************************
+**** GLOBALS
+*****************************************************************************/
+
+// SERIAL COMMAND INPUT
+enum command_t { READYFORCOMMAND, FEED, PICK, CLOSE, CONFIG };
+command_t pcCommand = READYFORCOMMAND;
+int pcCommandPos = 0;
+
+enum config_t { NONE, LANE };
+config_t pcConfig = NONE;
+
+enum lane_t { UNSELECTED, ZERO, ONE };
+lane_t selectedLane = UNSELECTED;
+
+// LANE STATES
+enum laneState_t { IDLE, PICKING, FEEDING, REVERSING };
+
+laneState_t lane0State = IDLE;
+laneState_t lane1State = IDLE;
+
+// LANE EDGE STATES
+int lane0LastEdge = 0;
+int lane1LastEdge = 0;
+
+// LANE EDGE COUNTERS
+int lane0FeedEdge = 0;
+int lane1FeedEdge = 0;
+
+// NUMBER OF POSITIONS TO FEED THROUGH
+int lane0FeedDistance = 1; // 1 = 2mm, 2 = 4mm
+int lane1FeedDistance = 1;
+
+// LOOP COUNT FOR BUTTONS (incase Timer is too slow)
+int button0PressCount = 0;
+int button1PressCount = 0;
+
+// FEEDER END BUTTON STATES
+int button0LastState = 0;
+int button1LastState = 0;
+
+// FEED STATE
+bool lane0Feed = 0;
+bool lane1Feed = 0;
+
+// PICKUP STATE
+bool tape0Takeup = 0;
+bool tape1Takeup = 0;
+
+// FEED STOPPER
+Timeout lane0Feedout;
+Timeout lane1Feedout;
+
+// PICKUP STOPPER
+Timeout lane0Pickupout;
+Timeout lane1Pickupout;
+
+/*****************************************************************************
+**** HARDWARE
+*****************************************************************************/
+
+// SOLENOIDS (TAPE COVER) - keep above usb to turn off quickly
+DigitalOut SOLENOID_0(PIN_SOLCTL_0, 0);
+DigitalOut SOLENOID_1(PIN_SOLCTL_1, 0);
+
+// USB VCOM UART for MBED Serial Port Driver
+USBSerial pc(0x1f00, 0x2012, 0x0001, false);
+
+// RS485
+//Serial control(PIN_UART_TXD, PIN_UART_RXD, 115200);
+DigitalOut RS485_DIR(PIN_RS485_DIR);
+
+// MOTOR DRIVERS - FEED
+HBridge feedMotor1(PIN_H1_IN1,PIN_H1_IN2);
+HBridge feedMotor0(PIN_H1_IN3,PIN_H1_IN4);
+
+// MOTOR DRIVERS - TAPE
+HBridge tapeMotor0(PIN_H2_IN2, PIN_H2_IN1);
+HBridge tapeMotor1(PIN_H2_IN4, PIN_H2_IN3);
+
+// GATES
+InterruptIn LN0_FEEDGATE(PIN_GATE_0);
+InterruptIn LN1_FEEDGATE(PIN_GATE_1);
+InterruptIn LN0_TAPEGATE(PIN_GATE_2);
+InterruptIn LN1_TAPEGATE(PIN_GATE_3);
+
+// FEEDER END BUTTONS
+InterruptIn BUTTON_GREEN_0(PIN_BTN_GREEN_0);
+InterruptIn BUTTON_GREEN_1(PIN_BTN_GREEN_1);
+
+InterruptIn BUTTON_YELLOW_0(PIN_LED_YELLOW_0);
+InterruptIn BUTTON_YELLOW_1(PIN_LED_YELLOW_1);
+
+InterruptIn BUTTON_BOARD_FEED(PIN_BOARD_FEED);
+
+// FEEDER END LEDS
+DigitalOut LED_0(PIN_BTN_LED_0);
+DigitalOut LED_1(PIN_BTN_LED_1);
+
+// DIGITAL CONTROL INPUT
+InterruptIn LANEIN_0(PIN_LANECTL_0);
+InterruptIn LANEIN_1(PIN_LANECTL_1);
+
+
+
+/*****************************************************************************
+**** TAPE SLACK PICKUP
+*****************************************************************************/
+
+void stopTapeL0() 
+{ 
+    if (LN0_TAPEGATE)
+    {
+        tape0Takeup = 0; 
+        tapeMotor0.Coast(); 
+    }
+}
+
+
+void stopTapeL1() 
+{ 
+    if (LN1_TAPEGATE)
+    {
+        tape1Takeup = 0; 
+        tapeMotor1.Coast(); 
+    }
+}
+
+
+/*****************************************************************************
+**** BUTTON INTERRUPTS
+*****************************************************************************/
+
+void button_yellow_0_int()
+{
+    pc.printf("Yellow Button 0 Press\r\n");
+}
+
+void button_yellow_1_int()
+{
+    pc.printf("Yellow Button 1 Press\r\n");
+}
+
+
+/*****************************************************************************
+**** LANE 0 FEED CONTROL
+*****************************************************************************/
+
+void setLane0Picking()
+{
+    lane0State = PICKING;
+    
+    //todo: PwmOut
+    SOLENOID_0 = 1;
+}
+
+void setLane0Feeding()
+{
+    lane0State = FEEDING;
+    lane0FeedEdge = 0;
+    lane0LastEdge = LN0_FEEDGATE;
+    
+    // solenoid release
+    SOLENOID_0 = 0;
+    
+    lane0Feed = 1;
+    // motor on
+    feedMotor0.Forward();
+}
+
+void setLane0Reversing()
+{
+    feedMotor0.Brake(); // yes..  this is only going to brake for a few dozen uS...
+    
+    lane0State = REVERSING;
+    lane0FeedEdge = 0;
+    lane0LastEdge = LN0_FEEDGATE;
+    
+    // go backwards till we smack the stop
+    feedMotor0.Reverse();
+}
+
+
+/*****************************************************************************
+**** LANE 1 FEED CONTROL
+*****************************************************************************/
+
+void setLane1Picking()
+{
+    lane1State = PICKING;
+    
+    //todo: PwmOut
+    SOLENOID_1 = 1;
+}
+
+
+void setLane1Feeding()
+{
+    lane1State = FEEDING;
+    lane1FeedEdge = 0;
+    lane1LastEdge = LN0_FEEDGATE;
+    
+    // solenoid release
+    SOLENOID_1 = 0;
+    
+    lane1Feed = 1;
+    // motor on
+    feedMotor1.Forward();
+}
+
+void setLane1Reversing()
+{
+    feedMotor1.Brake(); // yes..  this is only going to brake for a few dozen uS...
+    
+    lane1Feed = 0;
+    
+    lane1State = REVERSING;
+    lane1FeedEdge = 0;
+    lane1LastEdge = LN0_FEEDGATE;
+    
+    // go backwards till we smack the stop
+    feedMotor1.Reverse();
+}
+
+void coastLane0()
+{
+    if (lane0State == IDLE)
+    {
+        feedMotor0.Coast();
+    }
+}
+
+void coastLane1()
+{
+    if (lane1State == IDLE)
+    {
+        feedMotor1.Coast();
+    }
+}
+
+void stopLane0Reverse()
+{
+    feedMotor0.Brake();
+    
+    lane0Feedout.attach(&coastLane0, 0.020);
+}
+
+void stopLane1Reverse()
+{
+    feedMotor1.Brake();
+    
+    lane1Feedout.attach(&coastLane1, 0.020);
+}
+
+/*****************************************************************************
+**** MAIN
+*****************************************************************************/
+
+
+int main() 
+{
+    // solenoids off
+    SOLENOID_0 = 0;
+    SOLENOID_1 = 0;
+    
+    // motors high impedance
+    feedMotor0.Coast();
+    feedMotor1.Coast();
+    tapeMotor0.Coast();
+    tapeMotor1.Coast();
+    
+    LED_0 = 1;
+    LED_1 = 1;
+        
+    // give me time to get serial port connected
+    wait(2);
+    
+    LED_0 = 0;
+    LED_1 = 0;
+    
+    // clear terminal screen
+    pc.printf("\x1Bc\x1B[2J");
+    
+    pc.printf("\r\nFeeder POST...\r\n\r\n");
+    
+    char mac[6];
+    mbed_mac_address(mac);
+    uint32_t devId = mac[3] << 16 | mac[4] << 8 | mac[5];
+    pc.printf("Feeder ID: %d [%#04x::%#04x::%#04x]\r\n\r\n", devId, mac[3], mac[4], mac[5]);
+    
+    pc.printf("Gate 0 (L0 Feed): %d\r\n", LN0_FEEDGATE.read());
+    pc.printf("Gate 1 (L1 Feed): %d\r\n", LN1_FEEDGATE.read());
+    pc.printf("Gate 2 (L0 Tape): %d\r\n", LN0_TAPEGATE.read());
+    pc.printf("Gate 3 (L1 Tape): %d\r\n", LN1_TAPEGATE.read());
+    pc.printf("\r\n---\r\n");
+    
+    pc.printf("Green Button 0 (L0): %d\r\n", BUTTON_GREEN_0.read());
+    pc.printf("Green Button 1 (L1): %d\r\n", BUTTON_GREEN_1.read());
+    pc.printf("Yellow Button 0 (L0): %d\r\n", BUTTON_YELLOW_0.read());
+    pc.printf("Yellow Button 1 (L1): %d\r\n", BUTTON_YELLOW_1.read());
+    pc.printf("\r\n---\r\n");
+    
+    pc.printf("Lane 0 Control: %d\r\n", LANEIN_0.read());
+    pc.printf("Lane 1 Control: %d\r\n", LANEIN_0.read());
+    pc.printf("\r\n---\r\n");
+    pc.printf("END\r\n\r\n");
+    
+    // make sure motors are at their end stops
+    feedMotor0.Reverse();
+    wait_ms(50);
+    feedMotor0.Coast();
+    
+    // one after another, stall current is ~750mA per motor
+    feedMotor1.Reverse();
+    wait_ms(50);
+    feedMotor1.Coast();
+    
+    // cover tape pickup interrupts
+    /* Moved to main loop
+    LN0_TAPEGATE.rise(&L0_Tape_int);
+    LN0_TAPEGATE.fall(&L0_Tape_int);
+    LN1_TAPEGATE.rise(&L1_Tape_int);
+    LN1_TAPEGATE.fall(&L1_Tape_int);
+    */
+    
+    // button/gate state temp
+    int b0 = 0;
+    int b1 = 0;
+    uint8_t c = 0;
+    
+    // timer for button debouncing. oldass hardware buttons are bouncy!
+    Timer button0Time;
+    Timer button1Time;
+    
+    while(true)
+    {
+        /**********************************************************************
+        ** PC USB COMMS
+        **********************************************************************/
+        // no pc comms checking when feeding, can't afford the time
+        if (lane0State == IDLE && lane1State == IDLE)
+        { 
+            while (pc.readable())
+            {
+                c = pc.getc();
+                pc.putc(c);
+            
+                switch (pcCommand)
+                {
+                    case READYFORCOMMAND:
+                        if (c == 'F')
+                        { 
+                            pcCommand = FEED;
+                            pc.printf("\r\nFeed: ");
+                        }
+                        else if (c == 'P')
+                        {
+                            pcCommand = PICK;
+                            pc.printf("\r\nPick: ");
+                        }
+                        else if (c == 'E')
+                        {
+                            pcCommand = CLOSE;
+                            pc.printf("\r\nClose: ");
+                        }
+                        else if (c == 'C')
+                        {
+                            pcCommand = CONFIG;
+                            pc.printf("\r\nConfig: ");
+                        }
+                        break;
+                    case FEED:
+                        if (c == '0')
+                        {
+                            pc.printf("\rLane 0 Feeding\r\n");
+                            setLane0Feeding();
+                        }
+                        else if (c == '1')
+                        {
+                            pc.printf("\rLane 1 Feeding\r\n");
+                            setLane1Feeding();
+                        }
+                        
+                        pcCommand = READYFORCOMMAND;
+                        break;
+                    case PICK:
+                        if (c == '0')
+                        {
+                            pc.printf("\rLane 0 Picking\r\n");
+                            
+                            setLane0Picking();
+                        }
+                        else if (c == '1')
+                        {
+                            pc.printf("\rLane 1 Picking\r\n");
+                            
+                            setLane1Picking();
+                        }
+                            
+                        pcCommand = READYFORCOMMAND;
+                        break;
+                    case CLOSE:
+                        if (c == '0')
+                        {
+                            pc.printf("\rLane 0 Closing\r\n");
+                            
+                            SOLENOID_0 = 0;
+                            lane0State = IDLE;
+                        }
+                        else if (c == '1')
+                        {
+                            pc.printf("\rLane 1 Closing\r\n");
+                            
+                            SOLENOID_1 = 0;
+                            lane1State = IDLE;
+                        }
+                            
+                        pcCommand = READYFORCOMMAND;
+                        break;
+                    case CONFIG:
+                        pcCommandPos++;
+                        if (pcConfig == NONE)
+                        {
+                            if (c == 'L')
+                                pcConfig = LANE;
+                            else
+                                pcCommand = READYFORCOMMAND;
+                        }
+                        else if (pcConfig == LANE && selectedLane == UNSELECTED)
+                        {
+                            if (c == '0')
+                                selectedLane = ZERO;
+                            else if (c == '1')
+                                selectedLane = ONE;
+                            else
+                            {
+                                pcCommand = READYFORCOMMAND;
+                                pcConfig = NONE;
+                            }
+                        }
+                        else if (pcConfig == LANE)
+                        {
+                            if (selectedLane == ZERO)
+                                lane0FeedDistance = c == '1' ? 1 : 2;
+                            else
+                                lane1FeedDistance = c == '1' ? 1 : 2;
+                                
+                            selectedLane = UNSELECTED;
+                            pcCommand = READYFORCOMMAND;
+                            pcConfig = NONE;
+                        }
+                        break;
+                    default:
+                        break;
+                }
+            }
+        }
+            
+        
+        LED_0 = 1; // for timing check with oscope/logic analyser
+        
+        /**********************************************************************
+        ** BUTTON CHECK
+        **********************************************************************/
+        if (lane0State != FEEDING)
+        {
+            b0 = BUTTON_GREEN_0; // read states
+            b1 = BUTTON_GREEN_1;
+            
+            // BUTTON 0
+            if (b0 == button0LastState && b0) // button0 is pressed and was pressed last time too
+            {   
+                if (lane0State == IDLE)
+                {
+                    if (button0Time.read_ms() > 100) // wait for button state to be stable for 100ms
+                    {
+                        button0Time.reset();
+                        button0Time.stop(); // no need to keep counting
+                        
+                        pc.printf("Picking 0\r\n");
+                        button0PressCount = 0;
+                        setLane0Picking(); // open solenoid while button is down
+                    }
+                }
+            }
+            else if (!b0 && b0 != button0LastState) // low transition - button released
+            {
+                button0LastState = b0;
+                button0PressCount = 0;
+                
+                if (lane0State == PICKING) // not just a bounce
+                {
+                    pc.printf("Feeding 0\r\n");
+                    setLane0Feeding(); // button has been released, feed one component
+                }
+            }
+            else // high transition
+            {
+                if (b0) // button pressed
+                {
+                    button0Time.reset();
+                    button0Time.start();
+                }
+                button0PressCount = 0;
+            }
+            
+            button0LastState = b0;
+        }
+        
+        if (lane1State != FEEDING)
+        {
+            // BUTTON 1
+            if (b1 == button1LastState && b1) // button0 is pressed and was pressed last time too
+            {
+                if (lane1State == IDLE)
+                {
+                    if (button1Time.read_ms() > 100)
+                    {
+                        button1Time.reset();
+                        button1Time.stop();
+                        
+                        pc.printf("Picking 1\r\n");
+                        button1PressCount = 0;
+                        setLane1Picking();
+                    }
+                }
+            }
+            else if (!b1 && b1 != button1LastState) // low transition - button released
+            {
+                button1LastState = b1;
+                button1PressCount = 0;
+                
+                if (lane1State == PICKING)
+                {
+                    pc.printf("Feeding 1\r\n");
+                    setLane1Feeding();
+                }
+            }
+            else // high transition
+            {
+                if (b1)
+                {
+                    button1Time.reset();
+                    button1Time.start();
+                }
+                button1LastState = b1;
+                button1PressCount = 0;
+            }
+        }
+        
+        /**********************************************************************
+        ** ENCODER CHECK
+        **********************************************************************/
+        
+        b0 = LN0_FEEDGATE;
+        b1 = LN1_FEEDGATE;
+        
+        // LANE 0
+        if (lane0State == FEEDING || lane0State == REVERSING)
+        {
+            if (lane0LastEdge != b0)
+            {
+                lane0FeedEdge++;
+            }
+        }
+        lane0LastEdge = b0;
+        
+        // off stop, gap, past stop
+        if (lane0State == FEEDING && 
+            lane0FeedEdge > (lane0FeedDistance * FEED_FWD_ENC_PULSE))
+        {
+            lane0FeedEdge = 0;
+            feedMotor0.Brake();
+            pc.printf("R0\r\n");
+            setLane0Reversing();
+        }
+        // gap, return to stop
+        else if (lane0State == REVERSING && lane0FeedEdge > 1)
+        {
+            lane0State = IDLE;
+            lane0Feedout.attach(&stopLane0Reverse, 0.020);
+            pc.printf("Idle 0\r\n");
+        }
+        
+        // LANE 1
+        if (lane1State == FEEDING || lane1State == REVERSING)
+        {
+            if (lane1LastEdge != b1)
+            {
+                lane1FeedEdge++;
+            }
+        }
+        lane1LastEdge = b1;
+        
+        // off stop, gap, past stop
+        if (lane1State == FEEDING && 
+            lane1FeedEdge > (lane1FeedDistance * FEED_FWD_ENC_PULSE))
+        {
+            lane1FeedEdge = 0;
+            feedMotor1.Brake();
+            pc.printf("R1\r\n");
+            setLane1Reversing();
+        }
+        // gap, return to stop
+        else if (lane1State == REVERSING && lane1FeedEdge > 1)
+        {
+            lane1State = IDLE;
+            lane1Feedout.attach(&stopLane1Reverse, 0.020);
+            pc.printf("Idle 1\r\n");
+        }
+        
+        /**********************************************************************
+        ** COVER TAPE CHECK
+        **********************************************************************/
+        b0 = LN0_TAPEGATE;
+        b1 = LN1_TAPEGATE;
+        
+        // LANE 0
+        if (!b0 && !tape0Takeup)
+        {
+            tape0Takeup = 1;
+            tapeMotor0.Forward();
+            lane0Pickupout.attach(&stopTapeL0, TAPE_MAX_PULL_TIME);
+        }
+        else if (b0)
+        {
+            stopTapeL0();
+        }
+        
+        // LANE 1
+        if (!b1 && !tape1Takeup)
+        {
+            tape1Takeup = 1;
+            tapeMotor1.Forward();
+            lane1Pickupout.attach(&stopTapeL1, TAPE_MAX_PULL_TIME);
+        }
+        else if (b1)
+        {
+            stopTapeL1();
+        }
+        
+        LED_0 = 0; // for timing check
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Thu Feb 02 19:18:12 2017 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/ad3be0349dc5
\ No newline at end of file