Some variable to store motor turning speed

Hi guys got a question that im not sure how to implement in my code so any help would be great thanks.

Ive got 3 sensors lets name them S1, S2 and S3 each of them give a reading of up to 255

What i would like to do is if s1 < s2 turn (this speed) once it goes through the whole loop and s1 is still smaller than s2 turn ( a bit faster) and the speed just keeps going up until one of my other if statements are true then it resets to the first turning speed .

so basicly my robot must turn and turn faster and faster untill the other if statement is true.

Is this possible?

Its probably simple to some of you but I cant rap my head around it yet :astonished:

Thanks in advance.

Yes it is possible. But your decsription is not very clear

once it goes through the whole loop

The Arduino might repeat loop() in a millisecond - that does not give much time for your motor to do anything, so I suspect you have something else in mind.

If you have code, post it so we can see what you can see.

...R

Hi robin ok here is my code, just too take note i cant really use delays in this code.

#include <VirtualWire.h>
#undef int
#undef abs
#undef double
#undef float
#undef round
#define usTRIG 4 // no 12, 10 and 7 is out
#define usECHO1 11
#define usECHO2 8
#define usECHO3 9
char data;
unsigned long t1,t2,t3;//timers

int M1INA=14;
int M1INB=15;
int PWM1=5;//Motor 1
int M2INA=16;
int M2INB=17;
int PWM2=6;//Motor 2

void setup()
{
  Serial.begin(9600);
  pinMode(usTRIG,OUTPUT);
  digitalWrite(usTRIG,LOW);
  pinMode(usECHO1,INPUT);
  pinMode(usECHO2,INPUT);
  pinMode(usECHO3,INPUT);
  vw_set_ptt_inverted(true);
  vw_setup(2000);
  vw_set_rx_pin(2);
  vw_rx_start();
  pinMode(13,OUTPUT);

  pinMode(M1INA,OUTPUT);
  pinMode(M1INB,OUTPUT);
  pinMode(PWM1,OUTPUT);
  pinMode(M2INA,OUTPUT);
  pinMode(M2INB,OUTPUT);
  pinMode(PWM2,OUTPUT);

  digitalWrite(M1INA,LOW);
  digitalWrite(M1INB,HIGH);
  digitalWrite(M2INA,LOW);
  digitalWrite(M2INB,HIGH);

  TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM00); 
  TCCR0B = _BV(CS00);

}

void loop()
{    
  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;
  if (vw_get_message(buf, &buflen)) // Non-blocking
  {
    int i;
    digitalWrite(13, true); // Flash a light to show received good message
    for (i = 0; i < buflen; i++)
    {
      if(buf[i] == 'D'){
        digitalWrite(usTRIG,LOW);
        delayMicroseconds(10);
        digitalWrite(usTRIG,HIGH);
        delayMicroseconds(10);
        digitalWrite(usTRIG,LOW);
        t1=pulseIn(usECHO1,HIGH)/29;//return pulse length in uS
      }
      if(buf[i] == 'C'){
        digitalWrite(usTRIG,LOW);
        delayMicroseconds(10);
        digitalWrite(usTRIG,HIGH);
        delayMicroseconds(10);
        digitalWrite(usTRIG,LOW);
        t2=pulseIn(usECHO2,HIGH)/29;
      }
      if(buf[i] == 'E'){
        digitalWrite(usTRIG,LOW);
        delayMicroseconds(10);
        digitalWrite(usTRIG,HIGH);
        delayMicroseconds(10);
        digitalWrite(usTRIG,LOW);
        t3=pulseIn(usECHO3,HIGH)/29;
        Serial.print(t1);
        Serial.print("\t");
        Serial.print(t2);
        Serial.print("\t");
        Serial.println(t3);
      }
    }
    digitalWrite(13, false);
  }
  if(t2 < 250 && (t1 < 250||t3 < 250) && t1 > 40 && t2 > 40 && t3>40){
    if(t2 < t1 && t2 < t3){
      analogWrite(PWM1,t2);//when this statement is true and  t3<t2 again the else if resets to 180 again
      analogWrite(PWM2,t2);
    }
    else if (t3 < t2){
      analogWrite(PWM1,180);//This needs to start of at 180 and each time it is true go faster so the turning is faster until the first if statement is true then reset to 180 again
 
      analogWrite(PWM2,170);// I want this to be a constant speed
    }
    else if (t1 < t2){
      analogWrite(PWM1,210);
      analogWrite(PWM2,230);
    }
  }
  
  else{
    analogWrite(PWM1,0);
    analogWrite(PWM2,0);
  }
  
}

I don't see S1 in your code so it is a bit hard to relate it to your original post

You have TCCR0A = in your code but you have no explanantion of what that is supposed to achieve. How are we supposed to guess?

You have som very complex IF statements - can you describe what they are doing?

You have not responded to my comment about the speed at which loop() repeats.

...R

I don't see S1 in your code so it is a bit hard to relate it to your original post

Hi Robin sorry man i changed it to t1, t2 and t3 now

You have TCCR0A = in your code but you have no explanation of what that is supposed to achieve. How are we supposed to guess?

That is to change my pwm fequency to 16khz

You have som very complex IF statements - can you describe what they are doing?

Yes of course I can, ok the first if statement is just so that if my sensors dont get a signal the motors stop.
The second if statement is if true both motors go forward, im using the distance from sensor t2 to pwm the motors so if the distance from the sensor is 100cm the motors will run on 100pwm duty cycle.

Then the first and second else if statements are for turning left and right and thats where my problem is.

You have not responded to my comment about the speed at which loop() repeats.

Hmmm I think the loop repeats every 600ms if either left or right turning else if statement is true increase the one motors speed with small increments maybe like 5 or 10 pwm each time it loops

Thanks for your help Robin.

Thanks for the explanations.

I'm still not clear about the long IF statement because it seems to encapsulate all the others.

It would also help if you explain the purpose of the received message which seems to determine which ping is measured

Dividing an integer by 29 will likely give strange results. Why not use the raw (undivided) values, or divide by a power of 2 such as 16 or 32. I would not switch to floats - you won't actually have any better information. That may mean that you can't use t2 directly with analogWrite() - which may not be a bad idea.

You seem to be using fixed values with analogWrite() [eg 180]. If you want the speed to change why not use variables. Then you could probably take the analogWrite() commands right out of the IF statements.

That way you could have some code like

if (s1 < s2) {
   m1Val += increment;
   m2Val += increment;
}
//.....
analogWrite(pwm1, m1Val);
analogWrite(pwm2. m2Val);

...R

I'm still not clear about the long IF statement because it seems to encapsulate all the others.

It would also help if you explain the purpose of the received message which seems to determine which ping is measured

Yes if the ultrasonic sensors dont receive a ping signal they give a default value between 3000 and 6000

so that long if statement is so that if no signal is received none of the statements are true so the motors stop.
Im sending a wireless ping signal from one ultrasonic and the other 3 are the receivers.

That may mean that you can't use t2 directly with analogWrite() - which may not be a bad idea.

Why would it be better to not use t2 directly?, the reason im asking is because i need the value of sensors t2 to stay around 150cm so the higher the readings become the faster the motors must turn so that 150cm is maintained , I would rather not use t2 directly either but not sure how else to work it out so basicly I would like the motors to run at full pwm value(255) when t2 is 150cm or so but i also need smooth changing in pwm value dont want it to jump from 100pwm to 200pwm etc, any great ideas?

if (s1 < s2) {
   m1Val += increment;
   m2Val += increment;
}
//.....
analogWrite(pwm1, m1Val);
analogWrite(pwm2. m2Val);

Where would i adjust the increment or how much would the increment be ?
Sorry dont really understand this stuff that good yet

Thanks

OK. I can see that you have 3 ping sensors, but I don't understand why they are selected by something from virtualWire and I don't understand why there is any need to iterate through all the possible characters received. How many characters are received?

Also, I don't understand why you have the first 2 lines of

        digitalWrite(usTRIG,LOW);
        delayMicroseconds(10);
        digitalWrite(usTRIG,HIGH);
        delayMicroseconds(10);
        digitalWrite(usTRIG,LOW);

because the pin will already be LOW

I have no idea what size the incrment should be. You were the one who said you wanted the speed to increase. My assumption was that the increment would be fixed at the top of the program and each time it would increase the PWM value by that amount.

Of course I may have completely misunderstood what you want to happen.

There are three reasons why I would not use t2 directly. First, it requires the value of t2 to be manipulated into the correct range which may confuse other uses of the value, including for debugging. Second, you have said you want the speed to vary which would mean changing t2 away from its original value. And thirdly (and most importantly) I would write my code so that the pair of analogWrite()s only appears once in the program (probably as the last thing in loop() ) whereas you have them repeated 4 times.

By the way the piece of code I have include above is also repeated 3 times. If it was in a little function one version would be enough with reduced risk of mistakes in typing or copying.

...R

I should of added the other code would of made more sense to you sorry .

This is the sender code which runs off a nano, the purpose is to have the robot follow me.

#include <VirtualWire.h>
#undef int
#undef abs
#undef double
#undef float
#undef round
#define ultraTRIG 5
char *msg1 = "D",*msg2 = "C",*msg3 = "E";//dce
int timer = 200,timer2=200;
void setup()
{
  pinMode(ultraTRIG,OUTPUT);
  vw_set_ptt_inverted(true);
  vw_setup(2000);
  vw_set_tx_pin(3);
}

void loop()
{
  digitalWrite(13, true);
  
  vw_send((uint8_t *)msg1, strlen(msg1));
  vw_wait_tx();
  
  digitalWrite(13, false);
  digitalWrite(ultraTRIG,LOW);
  delayMicroseconds(timer);
  digitalWrite(ultraTRIG,HIGH);
  delayMicroseconds(10);
  digitalWrite(ultraTRIG,LOW);
  delay(timer2);
  digitalWrite(13, true);
  
  vw_send((uint8_t *)msg2, strlen(msg2));
  vw_wait_tx();
  
  digitalWrite(13, false);
  digitalWrite(ultraTRIG,LOW);
  delayMicroseconds(timer);
  digitalWrite(ultraTRIG,HIGH);
  delayMicroseconds(10);
  digitalWrite(ultraTRIG,LOW);
  delay(timer2);
  digitalWrite(13, true);
  
  vw_send((uint8_t *)msg3, strlen(msg3));
  vw_wait_tx();
  
  digitalWrite(13, false);
  digitalWrite(ultraTRIG,LOW);
  delayMicroseconds(timer);
  digitalWrite(ultraTRIG,HIGH);
  delayMicroseconds(10);
  digitalWrite(ultraTRIG,LOW);

  delay(300);
}

Ok so i think i should divide interger by 32 that is close enough doesnt make a big difference to the cm values

My assumption was that the increment would be fixed at the top of the program and each time it would increase the PWM value by that amount.

So would you put something like this at the top?

int increment = 20

If it was in a little function one version would be enough

Could you please perhaps explain how i can do this as ive lost you here?

Responding to Reply #8
I don't want to spend time on a second program. Please just describe what the received data is intended to achieve. Having a clear description will also be very useful for you.

Yes, something like that at the top.

You could make a function like this

void makePulse() {
    digitalWrite(usTRIG,HIGH);
    delayMicroseconds(10);
    digitalWrite(usTRIG,LOW);
}

and then use it like

 if(buf[i] == 'C'){
        makePulse();
        t2=pulseIn(usECHO2,HIGH)/29;
    }

Have you though carefully about the possibility that I have misunderstood what you want?

...R