Matthijs Muller
unread,Sep 12, 2022, 7:08:09 PM9/12/22Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to accelstepper
I call for a help here.
I am building an Artwork that comprises
of a sort of "flip clock", with 6 "digits" (secs, 10secs, min, 10 mins,
hrs, 10hrs) run with steppers.
I integrated an RTC and I managed to make the individual digits run on time.
But I also want to make the digits run "crazy" every once in a while.
And that is where the problems start.
I wrote several different variations which, when run individually, work.
I wrote a random selector (with switch case) and with timers, which works.
But once I start putting things together the problems start.
Some variations suddenly won't work, or inherit positions (or other settings) from previous variations, etc.
In
the beginning things were going terrible, but after I studied the
accelstepper library through the very helpfull "missing manual", things
started to work a bit better.
Nevertheless now I am on a point where
I manage to have two variations running (more or less), but several of
them not. And I don't see why.
In the current building phase I write for 1 or at the most 3 steppers. Once I have that running I expand with the other ones.
The whole should run on a Mega board. For now I test on an Uno.
I use stepperdrivers with microstepping 3200stp/evo.
I am able to program on a very basic level so this project is pushing me at (or rather over) the boundaries of my abilities.
I would be extremely gratefull when some of you might be able to help me on track again.
The
code has become fairly long so what I can do here, for a start, is
publish some relevant parts, to show my (simplistic) approach.
Many thanks in advance to all who take their time to give it a look!
Matthijs
// DECLARATIONS==================================
// TIME =========================================
#include <virtuabotixRTC.h> //Library used (pins 2,4,5)
virtuabotixRTC myRTC(5,4,2); //Clk,Dat,Rst
#include <elapsedMillis.h>
byte lastSecRead = 0; // get hold of last reading to see how much time past since
byte last10SecRead = 0;
byte lastMinRead = 0;
// ETC.
byte secDiff = 0; // track/calculate difference between the actual time and the lastRead
byte sec10Diff = 0;
byte minDiff = 0;
// ETC.
elapsedMillis writeTime; // for debugging
elapsedMillis startTime; // for startdelay in slowSwing
elapsedMillis onClockTimer1; // timers for the selection clock or variation
elapsedMillis offClockTimer1;
//ETC
int maxOnClockT1 = ((random (10,60)*1000*7); //setting max to ClockasAClock runs
int maxOffClockT1 = ((random (5,50)*1000); // setting the max for the variations (10-50secs)
bool onClockEnabled1 = true; // flag if random variation has finished, so clock can restart.
//ETC
bool offClockAll; // keeps track of the amount of steppers that do NOT run the clock
int countOffClockAll; // add all offClockAll true together
long ranMov1; // the randomMovement var
bool ranNeed1 = 1; // check if a new random is needed to avoid a stream of randoms
//ETC
//STEPPER========================================================================
#define FuRo 3200.0 // one Full Rotation set in the hardware at the driver!!!
//==================== // the number is according to the hardwaresettings
//==================== // Positions, (max)Speed, (max)Accel are related to
// the driversetting. By changing the setting in the driverhardware you only
// have to change the "FuRo" here and all should run well...
#include <AccelStepper.h>
const int stepPin1 = 8;
const int dirPin1 = 9;
const int enablePin1 = 12;
//the enablePin I will use differently, within a variation, outside the stepperdriver.
//stepper1.setPinsInverted (false, false, true); //(directionPin, stepPin, enablePin);
// ETC.
AccelStepper stepper1(AccelStepper::DRIVER, stepPin1, dirPin1, enablePin1);
// ETC.
bool isRunning;
bool runAllowed1 = false; // the main GO flag for the run routine
//ETC
//STEPPER POSITIONS ==============================
//// ABSOLUTE //// new position is hard-coded
int absTen[] = {FuRo,((FuRo/10)*1),((FuRo/10)*2),((FuRo/10)*3),((FuRo/10)*4),
((FuRo/10)*5),((FuRo/10)*6),((FuRo/10)*7),((FuRo/10)*8),((FuRo/10)*9)};
int absSix[] = {((FuRo/1)*1), ((FuRo/6)*1),((FuRo/6)*2),((FuRo/6)*3), ((FuRo/6)*4),((FuRo/6)*5)};
int absThree[] = {((FuRo/1)*1), ((FuRo/3)*1), ((FuRo/3)*2)};
//// RELATIVE //// new position is the many steps from current position
int relTen = absTen[1]; // the relative position-goal derides from the absolute position and from FuRo
int relSix = absSix[1];
int relThree = absThree[1];
// these are the vars for the switch-cases, which I will use extensively
byte swVar1 = 1; // var for switch of variations (only 1: 1 runs at a time)
//ETC
bool varDone = true; // the flag used to signal a variation is done(instead of a clock deciding to return)
int vibMax = 5; // max amount of vibrations
//=================================================
//NEW VARS DEVELOPED DURING TRIALS
int ranDintm1; // the intermediate random needed to create the randDirX
int ranDirX1; // the random that works like a "multiplier" for the direction - or +
//====================
// END OF DECLARATIONS
//=================================================
// SETUP
//=================================================
void setup() {
Serial.begin(9600);
randomSeed(analogRead(A0));
myRTC.updateTime(); // First: Read the clock
// print Time as a check if clock-module is still running fine
Serial.print(" Hour = "); Serial.print(myRTC.hours);Serial.print(":");
Serial.print (myRTC.minutes); Serial.print(":");Serial.println(myRTC.seconds);
ReadNewSec(); // initiate the calculations by once running them all to 0.
ReadNew10Sec();
ReadNewMin();
// ETC.
stepper1.setMaxSpeed(FuRo *4); // the maximum without load was more than 15000 for
stepper1.setAcceleration(FuRo *4); // both speed and acceleration at 3200 > (FuRo *5)
//stepper1.setMinPulseWidth(10); // the 6600 seems to work more reliable with 15 setting
// ETC. // be careful with this setting though
}
//====================
// END OF SETUP
//=================================================
// LOOP
//=================================================
updateTimeReadings();
selectAndRun();
runTheSteppers();
//====================
// END of LOOP
//================================================
// SELECTING THE VARIATION (or run the clock)
//================================================
void selectAndRun1() // the condition of maxOffClock motors has to be added
{
if (( onClockTimer1 < maxOnClockT1) || (varDone == false)){
// as long as maxOnClockTime isn't reached or a variation didn't say ready
runAllowed = true;
ranNeed1 = true; //flag the random in Need
randm1(); //(keep) running the randomizer for future random
calcRanDir(); // (keep) random seek for direction
ranMovPar(); // keep random seek for randomMovement Parameters
justJump(); // The Clock
offClockTimer1 = 0; // reset the offClockTimer for a future fresh start
}
else {
ranNeed1 = false;
switch (ranMov1) {
case 1:
if (offClockTimer1 > maxOffClockT1){ // when the timer is reached
offClockAll = false; // keep track of nr of off Clock motors
onClockEnabled1 = true;
onClockTimer1 = 0; // reset onClockTimer (so Clock restarts)
}
else { // as long as the maxOffClockTime is NOT met
runAllowed1 = true;
secSwing(); // The variation
offClockAll = true; // keep track of nr of off Clock motors
onClockEnabled1 = false;
}
break;
case 2:
if ((offClockTimer1 > maxOffClockT1)){
offClockAll = false;
onClockEnabled1 = true;
onClockTimer1 = 0;
}
else {
runAllowed1 = true;
secSwing(); // Another variation
offClockAll = true;
onClockEnabled1 = false;
}
break;
case 3:
if (offClockTimer1 > maxOffClockT1){
offClockAll = false;
onClockEnabled1 = true;
onClockTimer1 = 0;
}
else {
runAllowed1 = true;
moveRandom(); // Another variation
offClockAll = true;
onClockEnabled1 = false;
}
break;
}
}
}
//=================================================
// FUNCTIONS TIME
//=================================================
void updateTimeReadings() {
myRTC.updateTime(); // Read the clock
secDiff = (myRTC.seconds - lastSecRead); // Difference @secs between a certain moment and now
sec10Diff = (myRTC.seconds /10)- last10SecRead; // Difference @10secs
minDiff = (myRTC.minutes - lastMinRead); // Difference @mins
// ETC.
}
//=================================================
// FUNCTIONS MOVEMENT VARIATIONS
//=================================================
// JUMP 1/10th or 1/6th or 1/3rd evolution at a time
//==================================================
void justJump() // works! // each sec/min/etc the digit "jumps" to its new position
{ // sec, min, hrs > rotation/10 10sec,10min > rotation/6
// 10hrs > rotation / 3.
if ((secDiff < 1) && (lastSecRead - myRTC.seconds != 59) )
{ } // as long as one second isn't passed, do nothing & and a rollover so 60>0
else{
Reset();
runAllowed1 = true;
varDone = false;
stepper1.move(relTen);
stepper1.setMaxSpeed(FuRo*2); //The speed has to be defined AFTER move(To)
stepper1.setAcceleration(FuRo*1.5);
varDone = true;
ReadNewSec();
}
}
//RUN SECS IN GENTLE SWING
//==========================================================
// First the motor is switched off 1,5 second, so all is hanging down
// (this isn't programmed yet. But I expand the cases for that.)
// Then the motor gently starts swinging 1/10FuRo left, 1/10 right
void secSwing() // works within the selector, but with restrictions
{
switch (swVar1) //
{ // without a Reset it takes over settings from the previous
Reset(); // but with the Reset I loose track of my positions
varDone = false; // flag the variation in action
case 1:
// enablePin() = high; // or switch this with the funktion direct?
runAllowed1 = false;
if (startTime > 1500){ // timecondition for the start
runAllowed1 = true;
//enablePin() = low; // enablePin low = motor switched ON
//swVar1 = 2; // move to next case
} // without a break it automatically moves on
case 2: // this makes the first push > astable
runAllowed1 = true;
stepper1.setMaxSpeed(FuRo);
stepper1.setAcceleration(FuRo/10);
stepper1.moveTo(FuRo/10);
swVar1 = 3;
break;
case 3: // this starts an occilation
if (stepper1.distanceToGo() == 0){
stepper1.setMaxSpeed(FuRo);
stepper1.setAcceleration(FuRo/10);
stepper1.moveTo(-stepper1.currentPosition());
}
//if ( h == vibMax){ // I want to have the variation say: done
// varDone = true; // and then return to the selectionprogram/clock
// runAllowed1 = false; // but that doesn't work (yet). Switched back by the clock
//} // of the selector, makes me also lose track of the position.
break;
}}
// RANDOM MOVEMENT Variation
//=========================================
// RANDOM (random, steps, direction, acceleration, speed)
void moveRandom() // doesn't work within the selector
{
varDone = false; //flag the variation is running
Reset(); //without the reset it inherits settings
runAllowed = true;
stepper1.setMaxSpeed((rand() % 1500) + 1);
stepper1.setAcceleration((rand() % 500) + 1);
stepper1.moveTo((rand() % 32000) * ranDirX1);
varDone = true;
// if (stepper1.distanceToGo() == 0 ){ //again: trying to let the variation
// varDone = true; //flag the variation is ready //decide when to return to the selector
// } //this doesn't work ...
}
//=========================================
// RANDOMS CALCULATED
//=========================================
// ranNeed, a boolean that flags the need for a new random variation selection (rename in randSwNeed?)
// ranMov, the Switch-variable that defines which case is selected: resulting in random Movement.
void randm1(){ // calculate a random Movement (switch-case)
if ( ranNeed1 == true) { // to avoid repeated randoms
ranMov1 = random (1,4); // 1st nr is the minimum, 2nd nr is the "smaller than"!!!
} // else if
} // end
//ETC
//=========================================
// RANDOMIZING THE DIRECTION ==============
// ranDintm is an intermediate var needed to calculate a random direction
// randDirX is the random Directory + or - (Multiplier) that defines the direction
void calcRanDir1(){ // create a positive and negative random direction
ranDintm1 = random(0,2); // randomize between 0 and 1 // interim Var to aqquire randDirX
if (ranDintm > 0){ // if 1 > +1
ranDirX1 = 1;} // CW or CCW depending on wiring
else { // else -1
ranDirX1 = -1; // CCW or CW depending on wiring
}
}
//ETC
//=====================================================================
// RANDOMISED VARIATION
void ranMovPar(){
move2 = (random( FuRo * 2));
sMaxS = (random( FuRo * 2)+1);
aCell = (random( FuRo * 2)+1);
}
//==========================================
// RESET
//==========================================
void Reset() // created to avoid the variations inherit settings from each other
{ // but doing so I lose track of my position which is annoying but not impossible
// and still: inheriting occurs at some occasions
runAllowed1 = false; //running disabled
stepper1.disableOutputs(); //disable power
stepper1.setAcceleration(0);
stepper1.setMaxSpeed(0);
stepper1.setCurrentPosition(0); //Reset current position. "new home"
stepper1.enableOutputs();
runAllowed1 = true;
}
//=================================================
// RUN
//=================================================
void runTheSteppers()
{
if (runAllowed1 == true)
{
stepper1.enableOutputs(); //enable pins
stepper1.run(); //step the motor (this will step the motor by 1 step at each loop)
}
else //if the runallowed is FALSE, don't do anything
{
stepper1.disableOutputs(); //disable outputs
}
}
//ETC