Can Arduino fulfil my needs?

Hello everyone,

This is my very first post but I've been lurking for a few days (continuously)

I love the look, cost, ethos of Arduino and have ended up here from research into RepRap 3D Printers.

I am currently in the embodiment stage of a University Mechanical Design Engineering Project.

We are making a machine that can grind, heat, extrude, cool and spool plastic bottles for use as the RepRap feedstock.

As I say we're on our way and have a few ideas about how it will work. My programming background is a few projects with National Instruments LabVIEW and their CompactRIO.

This was my obvious choice for a control system for our project, but we would ultimately love to have it Open-Source, like RepRap

Enter Arduino!

So I thought I would give it a go and have spent the last day slapping together the sort of code I thought would be necessary to drive our Shredder.

Could someone take a look at it and comment as to its feasibility.

I think its also important to mention that the extruder and spooler will have similar control programmes that would have to all be run by the Arduino simultaneously, is that possible?

I'll stick with Arduino on a personal level anyway, looks fantastic!

Thanks for your time guys!

Chris

//Shredder Code
//code designed to run a shredder to shred plastic bottles.
//all of the components used are described below:

//define constants
const int shredTime = 5000 ;        //changing the value of this constant varies the duration the motor is on for
const int ledPrimedPin = 5 ;        //an LED that represents the shredder being in the Primed Case, attached to pin 5
const int ledActivePin = 6 ;        //an LED that represents the shredder being in the Active Case. attached to pin 6
const int buttonShredPin = 7 ;      //a push button used to move into the Active Case, attached to pin 7
const int buttonStopPin = 8 ;       //a push button used as a Stop Button [NOT YET USED], attached to pin 8
const int buttonSafetyPin = 9 ;     //a group of push buttons connected in series to determine the integrity of the shredding chamber, attached to pin 9
const int shredMotorPin = 10 ;      //a Solid State Relay used to connect the Shredder Motor to it's power source, attached to pin 10
const int doorLatchPin = 11 ;       //a Solid State Relay used to connect the Magnetic Door Latch to it's power source, attached to pin 11

//define variables
int shredCase = 0 ;                 //variable represents the case that the programme moves to
int lastShredCase = 0 ;             //variable which remembers the last case that the programme was in [NOT USED BUT THOUGHT IT MAY BE NECESSARY?]
int ledPrimedState = HIGH ;         //variable used to assign a value to the Primed LED
int ledActiveState = HIGH ;         //variable used to assign a value to the Active LED
int buttonShredState = HIGH ;       //variable used to store the value of the Shred Button
int buttonStopState = HIGH ;        //variable used to store the value of the Stop Button [NOT YET USED]
int buttonSafetyState = HIGH ;      //variable used to store the value of the Safety Buttons
int shredMotorState = HIGH ;        //variable used to assign a value to the Shredder Motor Relay
int doorLatchState = HIGH ;         //variable used to assign a value to the Magnetic Door Latch Relay

//Allocate pins as Input or Output
void setup()
{
  pinMode(ledPrimedPin, OUTPUT) ;
  pinMode(ledActivePin, OUTPUT) ;
  pinMode(buttonShredPin, INPUT) ;
  pinMode(buttonStopPin, INPUT) ;
  pinMode(buttonSafetyPin, INPUT) ;
  pinMode(shredMotorPin, OUTPUT) ;
  pinMode(doorLatchPin, OUTPUT) ;
}

//run the actual programme
//this will be a state machine and may take some doing...
void loop()
{
  switch(shredCase) {
    
    case 0:                                              //IDLE CASE
    ledPrimedState = LOW ;                               //the LEDs need to be set to high or low in each case
    digitalWrite(ledPrimedPin, ledPrimedState) ;         //the idle case uses neither.
    ledActiveState = LOW ;
    digitalWrite(ledActivePin, ledActiveState) ;
    buttonSafetyState = digitalRead(buttonSafetyPin) ;   //the progression from this case relies on safety switches
    if(buttonSafetyState = LOW){                         //safety button circuit will be pulled down. LOW is safe, HIGH is unsafe
    shredCase = 1 ;                                      //allows the programme to progress to Case 1 on next loop
    lastShredCase = 0;                                   //remembers that Case 0 was that which was called for this loop
    }
    else {
    shredCase = 0 ;                                      //the only thing that can happen here is progression or no change.
    lastShredCase = 0;                                   //therefore anything other than the safety going LOW forces the Case to not change.
    }
    break;                                               //break defines the end of the case - I'm hoping that at this point it starts the Loop again?
    
    case 1:                                                      //PRIMED CASE
    ledPrimedState = HIGH ;                                      //again the LEDs are set
    digitalWrite(ledPrimedPin, ledPrimedState) ;
    ledActiveState = LOW ;
    digitalWrite(ledActivePin, ledActiveState) ;
    buttonShredState = digitalRead(buttonShredPin) ;             //both the Safety and Shred Buttons are checked
    buttonSafetyState = digitalRead(buttonSafetyPin) ;
    if(buttonShredState = HIGH && buttonSafetyState = LOW) {     //if the Shred Button has been pressed and the Safety Circuit is complete (LOW) then the case progresses
      shredCase = 2 ;
      lastShredCase = 1 ;
    }
    else if(buttonShredState = LOW && buttonSafetyState = LOW) { //no change of state if the Shred Button isn't pressed
      shredCase = 1 ;
      lastShredCase = 1 ;
    }
    else if(buttonSafetyState = HIGH) {                          //if the Safety Circuit goes HIGH then the programme returns to the Idle Case, 0.
      shredCase = 0 ;
      lastShredCase = 1 ;
    }
    break;
    
    case 2:                                                 //ACTIVE CASE
    ledPrimedState = HIGH ;                                 //LEDs are set, at the moment it has been decided that both Primed and Active should be on here
    digitalWrite(ledPrimedPin, ledPrimed State) ;
    ledActiveState = HIGH ;
    digitalWrite(ledActivePin, ledActiveState) ;
    buttonSafetyState = digitalRead(buttonSafetyPin) ;      //since the shred button has already been used, just the safety is read here
    if(buttonSafetyState = LOW) {                           //this action section is the actual action of shredding
      doorLatchState = HIGH ;
      digitalWrite(doorLatchState, doorLatchPin) ;          //first off, the lid is Magnetically held shut. Magnet latch is on a SSR
      shredMotorState = HIGH ;                              //secondly, the Shredder Motor is turned on. Motor also on a separate SSR
      digitalWrite(shredMotorState, shredMotorPin) ;
      delay(shredTime) ;                                    //the Shred Time is used as a delay, leaving the motor running for a certain amount of time.
      shredMotorState = LOW ;                               //after the wait is over the Motor power is cut
      digitalWrite(shredMotorState, shredMotorPin) ;
      doorLatchState = LOW ;                                //after the Motor has powered down, the door is released.
      digitalWrite(doorLatchState, doorLatchPin) ;
      shredCase = 1 ;                                       //now the programme is sent back to the Primed Case
      lastShredCase = 2 ;
    }
    else if(buttonSafetyState = HIGH) {                     //the only other outcome is if the Safety Circuit is broken, then the programme returns to the Idle Case
      shredCase = 0 ;
      lastShredCase = 2
    }
    break ;
  }
}

Looks decent all-around, though two noteworthy things:

1: "if(buttonShredState = HIGH && buttonSafetyState = LOW)" This works flawlessly. It assigns 'HIGH' to buttonShredState and LOW to buttonSafetyState, which makes the && comparison compare HIGH and LOW, which results in false. A double = (==) is the thing you want to use here. Also, it is good practice to contain each comparison in its own set of brackets.

2: lots of comments. Which is good, but most don't say anything. Plenty of things can be geussed from the name of the variable, but the important details aren't mentioned.
For instance:

const int shredTime = 5000 ; //changing the value of this constant varies the duration the motor is on for

shredTime.. the time it takes to shred? Lets have a look at the comment.. the duration the motor is on.. geussed as much. Now.. 5000... seconds? thats over an hour! :o
Try to explain all the criteria the variable works under, and what unit(s) it uses (if any).

And yes, you can make it do multiple things, see the blinkWithoutDelay example on how to avoid delays. You'd probably put what you have in the loop function right now in its own, and turn the delays into delays based on the blinkWithoutDelay example. You could then make a similiar function for the other processes, and simply call each one from loop. The key thought process is, the arduino can only do one thing at a time. So whenever it should be waiting, let it do something else and return to your initial task when the time it should've been waiting is over. The trick is getting it to switch its task :wink:

PS: its nice that you add comments, too few people do this. I just figured I'd give you a little bit of advice to make the habbit even better :wink:

For readability I would add

 enum ShredState { IDLE, PRIMED, ACTIVE };

ShredState shredCase;
...
switch(shredCase) {
    case IDLE: ...
    case PRIMED: ...
    case ACTIVE: ...
}

See also -
http://www.arduino.cc/playground/Code/Enum

buttonSafetyState = digitalRead(buttonSafetyPin) ;

I would connect the SafetyButton to an interrupt routine so that it allways will be detected. Check - http://arduino.cc/en/Reference/AttachInterrupt

In the interrupt routine you set buttonSafetyState. This could also be an - enum AlarmState{ SAFE, ALARM }

include in setup:

attachInterrupt(0, safetyPressed, LOW );

and add a separate function

void safetyPressed()
{
   buttonSafetyState = ALARM;
}

buttonSafetyState must be declares as type AlarmState.

just my 2 cnts

Thanks alot guys,

exactly what I needed to hear. I will make the changes, and I was wondering about these 'interrupts' will give it a bash.

I guess I have some additional questions then since I can Arduino to the end.

Motors:
-will be using PWM to control two different DC motors. Will the arduino be able to output to this driver:

http://www.skpang.co.uk/catalog/product_info.php?products_id=580

and also read the current fedback:

'The FB output provides analog current-sense feedback of approximately 525 mV per amp.'

Sensors:
-Will be using a tonne of push buttons. will also be using a themistor / thermocouple and a linear pot.
Is there a certain value of voltage that the Arduino analogue Ins can pick up on?

Is it acceptable to post legitimate queries to this thread that I have about the project as I go?

I'm unsure whether my university tutors are well versed in the arduino code and I would much prefer the approval of you lot.. :slight_smile:

Thanks very much!

O also, is there a source of information anywhere for making multiple functions?

I would like to have something like

void shredder()
{
}

void extruder()
{
}

void spooler()
{
}

thanks!

Is there a certain value of voltage that the Arduino analogue Ins can pick up on?

The default for the 10 bit (0-1023 counts) A/D hardware for the Arduino is 0 to +5vdc, no negative voltage allowed. However by enabling internal voltage references and/or applying an external reference voltage to the aref pin one can have a lower top of range voltage represent 1023 counts.

Lefty

so bringing the roof down increases the resolution? does that change apply to all analogue pins simultaneously?

I do believe it does.
But be warned, you can't exceed that roof (it can't output a bigger number).

As for the functions, they're valid function structures. They have a return type (void, as in, it returns nothing), a name, and a collection of parameters (you defined them without any).

Can't help you with the hardware, not my area of expertise :-X

As for using this topic for your generic project inquiries, you may most definitly do this. It keeps the information regarding your project in a single location, making it easier for us to provide assistance.

so bringing the roof down increases the resolution? does that change apply to all analogue pins simultaneously?

Yes it does and it does apply to all the analog pins. However you can change the reference used between the various options at run time. That is you could change a reference then read a specific input pin and then change the reference back to read a different analog input pin. But note that there is a settling time after changing references and one needs to do a few dummy reads before the value is valid. Best to read up on the subject in the Atmel datasheets if planning on using external or optional reference voltages.
Lefty

O also, is there a source of information anywhere for making multiple functions?

I would like to have something like

You just can do that, in the same .pde file or you can build your own libraries (better wait for things to be stable.

Advice: reading (and building) the tutorials will answer many questions faster than asking them on the forum - http://www.arduino.cc/en/Tutorial/HomePage

ok thanks all.

I will continue to work through the tutorials.

When I actually start to put this stuff together you can expect to hear a lot from me...

I shall get stuck in, will post significant changes back here.

was just wondering what sort of power supply you guys use? I know the wall plug for the arduino can give a bit of juice but obviously I'm going to need something with a bit more kick for a 12V DC Motor that can swallow around 15A.

How would you guys power up something like that?

I know the wall plug for the arduino can give a bit of juice but obviously I'm going to need something with a bit more kick for a 12V DC Motor that can swallow around 15A.

If on a budget a popular route is to use a suitable PC power supply modded for standalone operation. However there are good buys to be found on E-bay and surplus electronics on-line stores for such power supplies. At that current level a switching power supply makes a lot more sense then the old linear power supplies.

http://cgi.ebay.com/DC-12V-15A-Universal-Regulated-Switching-Power-Supply-/220707275454?pt=LH_DefaultDomain_0&hash=item33632dc2be

http://cgi.ebay.com/12V-15A-DC-Universal-Regulated-Switching-Power-Supply-/270666259596?pt=LH_DefaultDomain_0&hash=item3f04f75c8c

ah so that's why you're a God Member! Thanks very much mate!

why is is that the further I go into this electronics business I wish that I lived in the states?

Unfortunately I'm English, and with it comes all that overpriced crap!

Any UK / EU suggestions?

Although now I do know what I'm looking for! Thanks very much!

So my exams are over and its back to the project. I've got a few questions about physically wiring the stuff up:

  1. Pull ups and downs. I get the idea but how do you know how big a resistor you should use?

  2. Any general advice for wiring and terminal standards? I'm looking at using an LCD along with all the other bits and it feels like I'm going to be using every pin on the MEGA. How do you avoid getting lost? Is there some generic break-out that allows the use of screw terminals ontop of the standard Arduino headers? What's the wiring convention that Arduinos use on their pins?

  3. Any recommended maximum lengths before TTL voltages get lost?

  4. I found Arduino through RepRap where they talk about Molex connectors, is this a good standard to adopt?

Thanks for your help :smiley: