Hello.
my name is Alan and i'm a new Arduino user.
I started to make the Gigantic Bubble Generator
It is working fine but the only thing I can not get working is the sirene.
I hope maybe one of you can have a look at the code and see what is wrong.
This is the link to the project
The code is:
/**
*
* BubbleBot Control Code
*
* By: Zvika Markfeld, Jonatan Bien, Uri Kareev
*
**/
#include <Servo.h>
#include <Wire.h>
#include "MCP23017.h"
#define upperBoundrySwitchPin 2
#define lowerBoundrySwitchPin 13
#define servoPin 3
#define fanPin 4
#define sirenPin 12
#define speakerPin 9
#define l298Ena 8
#define l298In1 7
#define l298In2 6
#define CTRL_JOY_UP 2
#define CTRL_JOY_RIGHT 4
#define CTRL_JOY_LEFT 8
#define CTRL_JOY_DOWN 16
#define CTRL_BUTTON1 32 // lower
#define CTRL_BUTTON2 64 // higher
#define CTRL_SWITCH 1
#define ROLLER_FORWARD 1
#define ROLLER_BACKWARD 2
#define ROLLER_IDLE 3
#define ROLLER_STOP 4
// 1:debug 2:info 3:warning 4:fatal
#define LOG_LEVEL 2
const int NUM_OF_SPREADS = 2;
const int SPREAD_SPEED = 30;
const int UNSPREAD_SPEED = 20;
const int SPREAD_DURATION = 2000;
const int SPREAD_DURATION_DECREASE_FACTOR = 3;
const int FAN_TURN_OFF_DELAY = 2000;
const int CHECK_LOWER_BOUNDARY_DELAY = 2000;
// Servo boundry values
const int arm_open_pos = 9;
const int arm_closed_pos = 60;
Servo myservo;
MCP23017 portExpander;
int rollerState;
int armPosition;
int sirenFreq = 100;
int sirenFreqStep;
int sirenMode;
int sirenFreqDir = 1;
void setup() {
Serial.begin(115200);
log(">> Initializing");
pinMode(lowerBoundrySwitchPin, INPUT);
pinMode(upperBoundrySwitchPin, INPUT);
pinMode(sirenPin, OUTPUT);
pinMode(l298Ena, OUTPUT);
pinMode(l298In1, OUTPUT);
pinMode(l298In2, OUTPUT);
pinMode(fanPin, OUTPUT);
digitalWrite(lowerBoundrySwitchPin, HIGH); // pullup
log(">> Bootstrapping I2C(1)");
Wire.begin();
log(">> Bootstrapping I2C(2)");
portExpander.SetDir(1,0); // all input
log(">> Bootstrapping I2C(3)");
portExpander.WriteByte(1, 255); // pullup
log(">> Attaching Arm Servo");
myservo.attach(servoPin);
setArm(arm_closed_pos);
log(">> Resetting machine state");
resetState();
}
void loop() {
if(isInManual()) {
digitalWrite(sirenPin, HIGH);
handleManual();
}
else {
digitalWrite(sirenPin, LOW);
handleAuto();
}
}
void handleManual() {
log("ALERT: entering MANUAL CONTROL");
while(isInManual()) {
sirenMode = 0;
// handle fan
if(isFanButtonPressed()) {
sirenMode = 1;
setFan(true);
}
else {
setFan(false);
}
// UP-DOWN
if(isJoyUp()) {
sirenMode = 2;
handleJoyUp();
}
else if(isJoyDown()) {
sirenMode = 2;
handleJoyDown();
}
else {
idle();
}
// LEFT_RIGHT
if(isJoyRight()) {
sirenMode = 3;
if(armPosition > arm_open_pos) {
setArm(armPosition - 1);
}
else {
setArm(arm_open_pos);
}
delayWithSirenUpdate(SPREAD_SPEED);
}
else if(isJoyLeft()) {
sirenMode = 3;
if(armPosition < arm_closed_pos) {
setArm(armPosition + 1);
}
else {
setArm(arm_closed_pos);
}
delayWithSirenUpdate(SPREAD_SPEED);
}
//>>>
//handleSiren();
}
log("exiting MANUAL CONTROL");
noTone(speakerPin);
}
void handleSiren() {
switch(sirenMode) {
case 0:
sirenFreqStep = 7;
break;
case 1:
sirenFreqStep = 75;
break;
case 2:
sirenFreqStep = 50;
break;
case 3:
sirenFreqStep = 50;
break;
}
tone(speakerPin, sirenFreq);
sirenFreq+= (sirenFreqStep * sirenFreqDir);
if(sirenFreq >= 2000 || sirenFreq <= 50) {
sirenFreqDir *= -1;
}
}
void delayWithSirenUpdate(int duration) {
long start = millis();
while(millis() - start < duration) {
//>>>
// handleSiren();
delay(10);
}
}
void handleJoyUp() {
log("detected JOY_UP", 1);
if(atUpperBoundary()) {
log("upper boundry reached, setting engine to idle", 1);
idle();
}
else if (rollerState != ROLLER_FORWARD) {
log("setting engine to forward", 1);
forward();
}
}
void setFan(boolean b) {
digitalWrite(fanPin, b ? HIGH : LOW);
}
void handleJoyDown() {
log("detected JOY_DOWN", 1);
if(atLowerBoundary()) {
log("upper boundry reached, setting engine to idle", 1);
idle();
}
else if (rollerState != ROLLER_BACKWARD) {
log("setting engine to backward", 1);
backward();
}
}
void forward() {
digitalWrite(l298Ena, HIGH);
digitalWrite(l298In1, LOW);
digitalWrite(l298In2, HIGH);
rollerState = ROLLER_FORWARD;
}
void backward() {
digitalWrite(l298Ena, HIGH);
digitalWrite(l298In1, HIGH);
digitalWrite(l298In2, LOW);
rollerState = ROLLER_BACKWARD;
}
void idle() {
digitalWrite(l298In1, LOW);
digitalWrite(l298In2, LOW);
digitalWrite(l298Ena, LOW);
rollerState = ROLLER_IDLE;
}
void stop() {
digitalWrite(l298In1, LOW);
digitalWrite(l298In2, LOW);
digitalWrite(l298Ena, LOW);
rollerState = ROLLER_STOP;
}
void setArm(int val) {
myservo.write(val);
armPosition = val;
}
void handleAuto() {
while(isInAuto()) {
forward();
log("waiting for upper boundry");
while(!atUpperBoundary()) {
if(isInManual()) {
return;
}
}
log("upper boundry detected");
idle();
log("switching fan on");
digitalWrite(fanPin, HIGH);
int pos;
int times;
for(times = 0; times < NUM_OF_SPREADS; ++times) {
// spread arms
for(pos = arm_closed_pos; pos>=arm_open_pos; pos-=1) {
if(isInManual()) {
return;
}
setArm(pos);
delay(SPREAD_SPEED);
}
int currDelay = SPREAD_DURATION * (SPREAD_DURATION_DECREASE_FACTOR - times) / SPREAD_DURATION_DECREASE_FACTOR;
log("waiting: ");
log(currDelay);
delay(currDelay);
// close arms
for(pos = arm_open_pos; pos <arm_closed_pos; pos += 1) {
if(isInManual()) {
return;
}
setArm(pos);
delay(UNSPREAD_SPEED);
}
}
// start bringing arms down
log("taking arms down");
backward();
delay(FAN_TURN_OFF_DELAY);
log("switching fan off");
digitalWrite(fanPin, LOW);
log("waiting for lower boundry");
// not needed, as FAN_TURN_OFF_DELAY is used
// delay(CHECK_LOWER_BOUNDARY_DELAY);
while (!atLowerBoundary() && !atUpperBoundary()) {
if(isInManual()) {
return;
}
}
idle();
if(atUpperBoundary()) {
log("ERROR: failed recognizing lower boundary, reached upper boundary. check lower boundary switch and restart", 3);
while(true);
}
else {
log("lower boundry detected");
}
}
}
void resetState() {
log("Resetting state");
setArm(arm_closed_pos);
forward();
log("waiting for upper boundry");
waitForUpperBoundary();
log("upper boundry detected, going down");
backward();
delay(CHECK_LOWER_BOUNDARY_DELAY);
log("waiting for lower boundry");
waitForLowerBoundary();
idle();
log("Machine state was reset");
}
/**
* buttons are pulled up, method will hopefully help preventing stupid programming errors due to the inverse logic
**/
boolean buttonEnabled(int value, int mask) {
return !(value & mask);
}
boolean isInManual() {
int buttonState = portExpander.ReadByte(1);
return buttonEnabled(buttonState, CTRL_SWITCH);
}
boolean isInAuto() {
return !isInManual();
}
boolean isFanButtonPressed() {
int buttonState = portExpander.ReadByte(1);
return buttonEnabled(buttonState, CTRL_BUTTON1);
}
boolean isJoyUp() {
int buttonState = portExpander.ReadByte(1);
return buttonEnabled(buttonState, CTRL_JOY_UP);
}
boolean isJoyDown() {
int buttonState = portExpander.ReadByte(1);
return buttonEnabled(buttonState, CTRL_JOY_DOWN);
}
boolean isJoyLeft() {
int buttonState = portExpander.ReadByte(1);
return buttonEnabled(buttonState, CTRL_JOY_LEFT);
}
boolean isJoyRight() {
int buttonState = portExpander.ReadByte(1);
return buttonEnabled(buttonState, CTRL_JOY_RIGHT);
}
void log(String msg) {
log(msg, 2);
}
void log(String msg, int level) {
if(level >= LOG_LEVEL) {
Serial.println(msg);
}
}
boolean atLowerBoundary() {
return (digitalRead(lowerBoundrySwitchPin) == LOW);
}
boolean atUpperBoundary() {
return (digitalRead(upperBoundrySwitchPin) == HIGH);
}
void waitForUpperBoundary() {
log("waiting for upper boundary");
while(!atUpperBoundary());
}
void waitForLowerBoundary() {
log("waiting for lower boundary");
while(!atLowerBoundary() && !atUpperBoundary());
if(atUpperBoundary()) {
log("ERROR: failed recognizing lower boundary, reached upper boundary. check lower boundary switch and restart", 3);
idle();
while(true);
}
}
regards Alan