RoadShark's Bug Game Thread
Moderators: adafruit_support_bill, adafruit
Please be positive and constructive with your questions and comments.
- adafruit_support_bill
- Posts: 88093
- Joined: Sat Feb 07, 2009 10:11 am
RoadShark's Bug Game Thread
Hi RoadShark - Let's continue the discussion started in your previous thread here: viewtopic.php?f=25&t=84806
- roadshark
- Posts: 652
- Joined: Sun Nov 29, 2015 5:53 am
Re: RoadShark's Bug Game Thread
:) At the moment I am using 8 I/O pins on the itsy. Would it be simpler to drive the servos (2) directly from these if possible or am I better of using the servo driver shield on the mega.
Here is what I have coded so far for the master.
I think an issue I might have is as there are two players, 2 bugs could be hit at the same or close to the same time. How to score this?
Here is what I have coded so far for the master.
Code: Select all
#include <AccelStepper.h>
#include <MultiStepper.h>
#include <Adafruit_PWMServoDriver.h>
#include <Adafruit_LEDBackpack.h>
#include <Wire.h> // Enable this line if using Arduino Uno, Mega, etc.
#include "Adafruit_LEDBackpack.h"
#include "Adafruit_GFX.h"
#include <SPI.h>
#include <Adafruit_VS1053.h>
int gameScore = 0;//Players score
int soundEffectPins[] = {22, 23, 24, 25, 26, 27, 28}; //22 is "Get Ready" 23 is "Game Over" 24 to 28 are bug whack sounds.
int bugWhackSensorPins[] = {29, 30, 31, 32, 33, 34};//29 is reset. Other pins are bugs
int ledStartSequencePins[] = {35, 36, 37, 38, 39};
int defTime = 30;
int state = 0;
int LimitSwitchPinHome [] = {40, 42, 44, 46, 48};
int LimitSwitchPinEnd [] = {41, 43, 45, 47, 49};
byte x = 0;
Adafruit_7segment matrixA = Adafruit_7segment();//Used to Display Score
Adafruit_7segment matrixB = Adafruit_7segment();//Used to Display countdown time
pinMode(LimitSwitchPinHome, INPUT_PULLUP);
pinMode(LimitSwitchPinEnd, INPUT_PULLUP);
pinMode(bugWhackSensorPins, INPUT_PULLUP);
pinMode(ledStartSequencePins, OUTPUT);
pinMode(soundEffectPins, OUTPUT);
void setup() {
Wire.begin(); // join i2c bus
// BugStepper class - derived from the AccelStepper class
class BugStepper: public AccelStepper
{
// Add additional state variables here
// BugStepper constructor - calls the base class AccelStepper constructor
BugStepper(uint8_t pin1, uint8_t pin2, uint8_t pin3, uint8_t pin4, bool enable = true)
: AccelStepper(AccelStepper::FULL4WIRE, pin1, pin2, pin3, pin4, enable)
{
// Add additional initialization here
}
// Add additional functions here
}
}
uint32_t countdownTimeout; // target end-time for the timeout.
void loop()
{
switch (state)
{
case 0://Sets players score to 0. Puts 30 seconds on the clock.When reset button is pushed a sound effect is played.
Wire.beginTransmission(8); // transmit to device #8
Wire.beginTransmission(9); // transmit to device #9
Wire.beginTransmission(10); // transmit to device #10
matrixA.begin(0x70);
matrixA.print(gameScore, DEC);
matrixA.writeDisplay();
//Displays timer
matrixB.begin(0x71);
matrixB.print(defTime);//Just puts 30 on the clock to indicate how many seconds in the round.
matrixB.writeDigitNum(2, 0x10, true);//decimal point.
matrixB.writeDisplay();
if (digitalRead (29) == LOW)
{
digitalWrite((22), HIGH);//Play sound effect "Get Ready To Whack".
state = 1;
}
break;
case 1://LED start lighting sequence.
for (int k = 0; k < ledStartSequenceCount; k++)//start of LED Start Sequence.
{
digitalWrite(ledStartSequence[k], HIGH);
delay(500);
digitalWrite(ledStartSequence[k], LOW);
}
// we are done with the startup light sequence
countdownTimeout = millis() + 30 * 1000; // Initialize countdown timer
state = 2; // transition to the next state
break;
case 2://Update the countdown timer and move the bugs
if (countdownTimeout - millis() > 0) // keep going
{
int secondsRemaining = (countdownTimeout - millis()) / 1000;// display time remaining
matrixB.begin(0x71);
matrixB.print(secondsRemaining);
matrixB.writeDigitNum(2, 0x10, true);//decimal point.
matrixB.writeDisplay();
// keep moving the bugs.
//bug scoring and link to sound effect player
if ((digitalRead (30) == LOW) || (digitalRead (34) == LOW)) //bug whack indication pin bug 1 or 5
{
digitalWrite((24), HIGH);//Play sound effect s1 of bug getting squashed.
playerScore = += 20;
}
if ((digitalRead (31) == LOW) || (digitalRead (33) == LOW)) //bug whack indication pin bug 2 and 4
{
digitalWrite((25), HIGH);//Play sound effect s2 of buggetting squashed.
playerScore = += 50;
}
if((digitalRead (32) == LOW) //bug whack indication pin bug 3
{
digitalWrite((26), HIGH);//Play sound effect s3 bug getting squashed.
playerScore = +=20
}
}
else
{
//play game over sound and return bugs to home cave
break;
}
}
}
- adafruit_support_bill
- Posts: 88093
- Joined: Sat Feb 07, 2009 10:11 am
Re: RoadShark's Bug Game Thread
I suppose it could be done either way. If you have pins to spare, the slave could always point the bug in the direction the motor is moving.Would it be simpler to drive the servos (2) directly from these if possible or am I better of using the servo driver shield on the mega.
In your 'play' phase of the game (state 2) there are no delays or time consuming operations, so the master should be polling those switches at a good rate and should not miss much. If it does become a problem, we could look at solutions like pin-change interrupts.I think an issue I might have is as there are two players, 2 bugs could be hit at the same or close to the same time. How to score this?
- roadshark
- Posts: 652
- Joined: Sun Nov 29, 2015 5:53 am
Re: RoadShark's Bug Game Thread
I think I have enough pins for the servo's to work of the itsy. The I/O pins I am using are for the motors Pins 5, 7, 9, 10 Limit pins A0, A1, A2, A3. I was planning to use Pins 11, 12 for servo 1 and pins A4 and A5 for servo two. Both servos use a commond Gnd pin on the itsy. Does the accelstepper library need to be on the master?
Is this piece of code is this how we send the data to the slaves?
Is this piece of code is this how we send the data to the slaves?
Code: Select all
//Send the bug moving information to the slaves
Wire.beginTransmission(8); // transmit to device #8
Wire.write("x is "); // sends five bytes
x++;
Wire.endTransmission(); // stop transmitting
Wire.beginTransmission(9); // transmit to device #9
Wire.write("x is "); // sends five bytes
Wire.endTransmission(); // stop transmitting
x++;
Wire.beginTransmission(10); // transmit to device #9
Wire.write("x is "); // sends five bytes
Wire.endTransmission(); // stop transmitting
x++;
- adafruit_support_bill
- Posts: 88093
- Joined: Sat Feb 07, 2009 10:11 am
Re: RoadShark's Bug Game Thread
Sounds like a good plan. No need for AccelStepper on the master, since it is not directly controlling any steppers.
And that is the way to talk to the slaves. Just replace the "x is " with something that the slave will understand.
And that is the way to talk to the slaves. Just replace the "x is " with something that the slave will understand.
- roadshark
- Posts: 652
- Joined: Sun Nov 29, 2015 5:53 am
Re: RoadShark's Bug Game Thread
This is the bit I do not understand (among other things;)) I guess I have to define some sort of command the slave recognises to do something like move the motors forwards at half speed. For example 8 1 R 1R5Just replace the "x is " with something that the slave will understand.
So Slave with the address of 8 motor 1 move R at moderate speed.
If the slave gets this command it would have to know that motor one is bugWacker1 and that R means to go right (normal direction) and that 1R5 means to move at 2000. This information would have to be defined in the set up?
I was thinking that maybe the slave (would it have enough memory seeing it has servo and accelstepper library) could already have this information in a program for example named PROG1. If it recieves this code from the master it executes the program like Motor one speed is 3000 Move to 2000 then turn servo and return and repeat until it receives notification from the master that the clock has run down so it goes home and re calibrates. Motor two does something similar.
If however it gets PROG2 it runs a similiar program with the difference being the speed parameter.
Or is this not how you do things. This is the code that I would use to communicate the slave with the master.
Code: Select all
void setup() {
Wire.begin(8); // join i2c bus with address #8
Wire.onReceive(receiveEvent); // register event
}
void loop() {
delay(100);
}
// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
while (1 < Wire.available()) { // loop through all but the last
char c = Wire.read(); // receive byte as a character
}
int x = Wire.read(); // receive byte as an integer
}
- adafruit_support_bill
- Posts: 88093
- Joined: Sat Feb 07, 2009 10:11 am
Re: RoadShark's Bug Game Thread
The address is not part of the command string - since you have already specified the address in the beginTransmission:For example 8 1 R 1R5
So Slave with the address of 8 motor 1 move R at moderate speed.
Code: Select all
Wire.beginTransmission(8); // transmit to device #8
If you take a look at the 3-character codes I suggested earlier, the top-level command handling could look something like:If the slave gets this command it would have to know that motor one is bugWacker1 and that R means to go right (normal direction) and that 1R5 means to move at 2000. This information would have to be defined in the set up?
Code: Select all
void CommandHandler(char[] commandString)
{
switch(commandString[1]) // second character is the actual command
{
case 'R':
case 'L':
MoveMotor(commandString); // move a motor
break;
case 'S':
StopMotor(commandString); // stop a motor
break;
case 'H':
HomeMotor(commandString); // home a motor
break
}
}
The MoveMotor command handler would look something like:
Code: Select all
void MoveMotor(char[] commandString)
{
long distance = 5000; // default to moving right (positive number)
if (commandString[1] == 'L')
{
distance = -5000; //go negative for a left move
}
float speed = (commandString[0] - '0') * 500; // set speed on a scale of 0-9
switch(commandString[0]) // first character specifies the motor
{
case '1':
bugWacker1.move(distance);
bugwhacker2.setMaxSpeed(speed);
break;
case '2':
bugWacker2.move(distance);
bugwhacker2.setMaxSpeed(speed);
break;
}
}
- roadshark
- Posts: 652
- Joined: Sun Nov 29, 2015 5:53 am
Re: RoadShark's Bug Game Thread
Wow! I will need a lot of coffee and munchies to unpack this!!
- roadshark
- Posts: 652
- Joined: Sun Nov 29, 2015 5:53 am
Re: RoadShark's Bug Game Thread
Ok so we have 2 functions. CommandHandler and MoveMotor.
The commandString holds the values passed from the Master.
The first byte is either a 1 or 2 indicating the motor.
The second byte is either a L, R, S, or H. indicating what the motor is to do.
If the master sends this information
Wire.beginTransmission(8); // transmit to device #8
Wire.write(1 H); // sends two bytes
Wire.endTransmission(); // stop transmitting and the slave recieves
Wire.begin(8); // join i2c bus with address #8
Wire.onReceive(receiveEvent); // register event
void receiveEvent(int howMany) {
while (1 < Wire.available()) { // loop through all but the last
char c = Wire.read(); //
How does the slave take this information and make it into the command string??
The commandString holds the values passed from the Master.
The first byte is either a 1 or 2 indicating the motor.
The second byte is either a L, R, S, or H. indicating what the motor is to do.
If the master sends this information
Wire.beginTransmission(8); // transmit to device #8
Wire.write(1 H); // sends two bytes
Wire.endTransmission(); // stop transmitting and the slave recieves
Wire.begin(8); // join i2c bus with address #8
Wire.onReceive(receiveEvent); // register event
void receiveEvent(int howMany) {
while (1 < Wire.available()) { // loop through all but the last
char c = Wire.read(); //
How does the slave take this information and make it into the command string??
- adafruit_support_bill
- Posts: 88093
- Joined: Sat Feb 07, 2009 10:11 am
Re: RoadShark's Bug Game Thread
Here is some (pre-coffee) code.
Code: Select all
// this function is registered as an event in setup()
void receiveEvent(int howMany)
{
char commandString[3]; //declare an array of (up to) 3 characters
int index = 0;
while (Wire.available())
{
commandString[i++] = Wire.read(); // stuff next character into array
}
CommandHandler(commandString); //call the commandHandler with the completed string
}
- roadshark
- Posts: 652
- Joined: Sun Nov 29, 2015 5:53 am
Re: RoadShark's Bug Game Thread
:) I assume this beverage will be sought after the Sunday morning pedal? The replacement itsy is in Australia. Hopefully it will read the usb.
The max speed I can get out of the motors is 4000.
[quote]float speed = (commandString[0] - '0') * 500; // set speed on a scale of 0-9[/quote
The lowest speed I would want the motors to travel (still experimenting) would be about 2000.
The max speed I can get out of the motors is 4000.
[quote]float speed = (commandString[0] - '0') * 500; // set speed on a scale of 0-9[/quote
The lowest speed I would want the motors to travel (still experimenting) would be about 2000.
- adafruit_support_bill
- Posts: 88093
- Joined: Sat Feb 07, 2009 10:11 am
Re: RoadShark's Bug Game Thread
To scale the characters '0'-'9' to 2000-4000, you can use 'map'.
Code: Select all
float speed = map(commandString[2], '0', '9', 2000, 4000);
- roadshark
- Posts: 652
- Joined: Sun Nov 29, 2015 5:53 am
Re: RoadShark's Bug Game Thread
Does this
Replace this
How do I go about coding the servo? As I am not using the servo driver shield like I originally intended but using the spare pins on the itsy I assume I do not need the associated library. So is this the way to go?
An argument I can use is that if the bugStepper1 is at 0 or home limit switch is Low then turn the servo 180 degrees.
If the bugStepper1 is at 2000 or the turn limit switch is low then turn the servo -180 degrees.
Code: Select all
float speed = map(commandString[2], '0', '9', 2000, 4000);
Code: Select all
float speed = (commandString[0] - '0') * 500;
Code: Select all
/* Sweep
by BANNED <http://BANNED.com>
This example code is in the public domain.
modified 8 Nov 2013
by Scott Fitzgerald
http://www.arduino.cc/en/Tutorial/Sweep
*/
#include <Servo.h>
Servo myservo; // create servo object to control a servo
// twelve servo objects can be created on most boards
int pos = 0; // variable to store the servo position
void setup() {
myservo.attach(9); // attaches the servo on pin 9 to the servo object
}
void loop() {
for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
// in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
}
If the bugStepper1 is at 2000 or the turn limit switch is low then turn the servo -180 degrees.
- adafruit_support_bill
- Posts: 88093
- Joined: Sat Feb 07, 2009 10:11 am
Re: RoadShark's Bug Game Thread
Yes.Does this
float speed = map(commandString[2], '0', '9', 2000, 4000);
Replace this
float speed = (commandString[0] - '0') * 500;
You have the right idea. Just use the standard Arduino Servo library.How do I go about coding the servo?
- roadshark
- Posts: 652
- Joined: Sun Nov 29, 2015 5:53 am
Re: RoadShark's Bug Game Thread
Is this how to create my servos object
Servo bugWhack1servo; // create servo object to control a servo on motor 1 rail
Servo bugWhack2servo; // create servo object to control a servo on motor 2 rail
int pos = 0; // variable to store the servo position
void setup()
bugWhack1servo.attach(11); // attaches the servo on pin 11 to the servo object
bugWhack2servo.attach(A4)//attaches the servo on pin A4 to the servo object
Servo bugWhack1servo; // create servo object to control a servo on motor 1 rail
Servo bugWhack2servo; // create servo object to control a servo on motor 2 rail
int pos = 0; // variable to store the servo position
void setup()
bugWhack1servo.attach(11); // attaches the servo on pin 11 to the servo object
bugWhack2servo.attach(A4)//attaches the servo on pin A4 to the servo object
Please be positive and constructive with your questions and comments.