State change random feature

ok so i have various states in order to accomplish my goal.

the code spends most of its time scanning for a rfid signal, when its detected it twitches the servos,

in a random period of time it will randomly select one of two other states, each of these have a secondry state that follows. these pairs operate the same servos as the rfid.

each "pair" of these states once complete return back to scanning for rfid.

reason for this is because i dont want the servos being activated from the rfid in the middle of the other states as it will cause damage to what the servos are being installed in.

anyway, im having difficulty making it choose one of the two "master" states randomly. (i.e choosing which one randomly)

heres the code i have done so far

#include <Wire.h>
#include <SPI.h>
#include <Servo.h>
#include <MFRC522.h>

 MFRC522 mfrc522(10, 9); // MFRC522 mfrc522(SS_PIN, RST_PIN)
 Servo fingers;
 Servo thumb;
 Servo wrist;
 int angle=0;
 String tagUID = "F5 7E C9 EF"; // String to store UID of tag. Change it with your tag's UID

 typedef enum
 {
  initialState,
  wantCheckrfid,
  want1,              //Fistclench,
  wantFistrelax,
  want2,              //Thumbsupclench,
  wantThumbsuprelax,
 } states;

// state machine variables
states state = initialState;
unsigned long lastStateChange = 0;
unsigned long timeInThisState = 1000;
 
 void setup() {
 fingers.attach(6);
 thumb.attach(7);
 wrist.attach(8);
  SPI.begin(); // Init SPI bus
 mfrc522.PCD_Init(); // Init MFRC522
 
 }

 void doStateChange ()
 {
  lastStateChange = millis ();
  timeInThisState = 1000;

  switch (state)
  {
    case initialState:
         state = wantCheckrfid;
         break;

   case wantCheckrfid:
   // Look for new cards
 if ( ! mfrc522.PICC_IsNewCardPresent()) {
 return;
 }
 // Select one of the cards
 if ( ! mfrc522.PICC_ReadCardSerial()) {
 return;
 }
 
 //Reading from the card
 String tag = "";
 for (byte i = 0; i < mfrc522.uid.size; i++)
 {
 tag.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
 tag.concat(String(mfrc522.uid.uidByte[i], HEX));
 }
 tag.toUpperCase();
 
 //Checking the card
 if (tag.substring(1) == tagUID) //change here the UID of the card/cards that you want to give access
 {
 // If UID of tag is matched.
 fingers.write(20);
 thumb.write(30);
 delay (120);
 fingers.write(0);
 thumb.write(0);
 }
    state = random(want1)+want2);
    timeInThisState = random 10000(50000);
    break;

    case want1:
    fingers.write(120);
    thumb.write(80);
    state = wantFistrelax;
    timeInThisState = 20000;
    break;

    case wantFistrelax:
    fingers.write(0);
    thumb.write(0);
    state = wantCheckrfid;
    timeInThisState = 3000;
    break;

    case want2:
    fingers.write(120);
    wrist.write(90);
    state = wantThumbsuprelax;
    timeInThisState = 20000;
    break;

    case wantThumbsuprelax:
    fingers.write(0);
    wrist.write(0);
    state = wantCheckrfid;
    timeInThisState = 3000;
    break;
  }
 }
  
 void loop() {

 if (millis () - lastStateChange >= timeInThisState)
     doStateChange ();
}

any help would be appreciated.

i know "random" only returns numbers, so i tried renaming the states to 1 and 2 without "want" but then it complained about needing an identifier.

on a side note, yes i know theres a cheeky "delay" in the rfid code, it shouldnt pose an issue as i couldnt work out how to add the delay using millis lol

You're missing a '('. What are you trying to do here?

state = random(want1)+want2));

expected ';' before ')' token

it had that first line highlighted

basically i need the code here to randomly select either want1 or want2

What do you mean? Have you tried changing that and compiling? Is the code you posted, your current sketch, exactly?

basically i need the code here to randomly select either want1 or want2

state = random(2)? want1 : want2;

holy hell it compiled without any further errors......it was that simple...

thank you, so much!!!! time to hook up the hardware and test it out.....when it comes in the post aha.

thank you aarg your a legend

And she/he is still alive too.
:grinning:

ok so here is my current code,

i got my hardware hooked up and ran into a problem.

#include <Wire.h>
#include <SPI.h>
#include <Servo.h>
#include <MFRC522.h>

 MFRC522 mfrc522(10, 9); // MFRC522 mfrc522(SS_PIN, RST_PIN)
 Servo fingers;
 Servo thumb;
 Servo wrist;
 int angle=0;
 String tagUID = "9A 71 1C B0"; // String to store UID of tag. Change it with your tag's UID

 typedef enum
 {
  initialState,
  wantCheckrfid,
  want1,              //Fistclench,
  wantFistrelax,
  want2,              //Thumbsupclench,
  wantThumbsuprelax,
 } states;

// state machine variables
states state = initialState;
unsigned long lastStateChange = 0;
unsigned long timeInThisState = 1000;
 
 void setup() {
 fingers.attach(4);
 thumb.attach(3);
 wrist.attach(2);
 //wrist2.attach(10)
 //pinktip.attach(9);
 //pinkybase.attach(8);
 //ringtip.attach(7);
 //ringbase.attach(6);
 //middletip.attach(5);
 //middlebase.attach(4);
 //indextip.attach(3);
 //indexbase.attach(2);
  SPI.begin(); // Init SPI bus
 mfrc522.PCD_Init(); // Init MFRC522
 
 }

 void doStateChange ()
 {
  lastStateChange = millis ();
  timeInThisState = 1000;

  switch (state)
  {
    case initialState:
         state = wantCheckrfid;
         break;

   case wantCheckrfid:
   // Look for new cards
 if ( ! mfrc522.PICC_IsNewCardPresent()) {
 return;
 }
 // Select one of the cards
 if ( ! mfrc522.PICC_ReadCardSerial()) {
 return;
 }
 
 //Reading from the card
 String tag = "";
 for (byte i = 0; i < mfrc522.uid.size; i++)
 {
 tag.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
 tag.concat(String(mfrc522.uid.uidByte[i], HEX));
 }
 tag.toUpperCase();
 
 //Checking the card
 if (tag.substring(1) == tagUID) //change here the UID of the card/cards that you want to give access
 {
 // If UID of tag is matched.
 fingers.write(20);
 thumb.write(30);
 delay (500);
 fingers.write(0);
 thumb.write(0);
 }
    state = random(2)? want1 : want2;
    timeInThisState = random (10000)+(50000);
    break;

    case want1:
    fingers.write(120);
    thumb.write(80);
    state = wantFistrelax;
    timeInThisState = 20000;
    break;

    case wantFistrelax:
    fingers.write(0);
    thumb.write(0);
    state = wantCheckrfid;
    timeInThisState = 3000;
    break;

    case want2:
    fingers.write(120);
    wrist.write(90);
    state = wantThumbsuprelax;
    timeInThisState = 20000;
    break;

    case wantThumbsuprelax:
    fingers.write(0);
    wrist.write(0);
    state = wantCheckrfid;
    timeInThisState = 3000;
    break;
  }
 }
  
 void loop() {

 if (millis () - lastStateChange >= timeInThisState)
     doStateChange ();
}

it gets to the first servo move in the card reading, moves the servo but doesnt actually return it back to 0 possition.

any ideas?

Think you better put some diagnostic print statements in the code at strategic locations to see if things/variables are what you think they are.

wouldnt even know how to do that

this is a combination of 2 functioning codes, granted one heavily modified.

im guessing you can see where the problem is, can you point me to it?

Use the Serial monitor to, um, monitor your program flow and varaibles. A primitive but entriely useful method to find errors or verify proper functioning.

barest minimum knowledge:

Serial.begin(...);
Serial.print(...);
Serial.println(...);

HTH, sry if you knew this.

a7

Do you expect A)

    timeInThisState = random (10000) + 50000;

or B)

    timeInThisState = random (10000 + 50000);

It isn't obvious what you mean, but it will do "A".

    timeInThisState = random (10000, 60000);

will do "B".

https://www.arduino.cc/reference/en/language/functions/random-numbers/random/

think this is what i need, a random length of time between those milliseconds

however, and admittedly i havent ran the serial diagnostics yet, it moves the servo from the rfid being detected but its not returning it back to the 0 possition, so that is the first hurdle i need to resolve, then progress onto any more that crop up. again, however though, i will address that in my code now as its an easy fix.

(thank you)

It's the same as

timeInThisState = random (10000) + 50000;

I suggest losing the parentheses. It's just confusing. Or use the two parameter version of random().

What part of the code is supposed to do that?

//Checking the card
 if (tag.substring(1) == tagUID) //change here the UID of the card/cards that you want to give access
 {
 // If UID of tag is matched.
 fingers.write(20);
 thumb.write(30);
 delay (500);
 fingers.write(0);
 thumb.write(0);
 }

this is the section that fails, it reads a valid rfid chip, moves the servo but doesnt return it to 0 i also think its moving the servo too far but cant confirm that right now.

ok so just thinking this.....does that need to be .write(-30); to return to 0 point?

Did you calibrate it for the physical zero position?

um?

No. Positions are absolute.

Use a small sketch for servos and see the positions different numbers move the servo to.

There's a simple example sketch in the IDE you coukd use,

a7

i thought so, so how come its not returning to 0 point?