Python lego robot

hello everyone, I’m trying to create a code that makes a robot cross a color field and speak the color it finds at once. the program works, but when the robot found the color, it repeats the color several times even when it is already in another color

Nice project idea! (And welcome to the list.)

My guess is you have a loop, and within it you work out the colour and then speak it. Then you go round the loop again.

It’s quite common to want to do an action only when an observable value has changed. The trick is to remember the last value on which you did the action so you have a value to compare against.

So we need a last_colour variable. Also, what do you do if you’re not doing the action? In order not to spin frantically, in robot projects, you often want wait (sleep), before going round again.

Something like (I have not tested this):

import time

last_colour = None
while (True):  # this is the loop you may already have
    colour = get_colour()
    if colour == last_colour:
        time.sleep(1.0)
    else:
        announce_colour(colour)
        last_colour = colour

If I’ve misunderstood, post us some code. (Put it between triple back-quotes to make it show nicely.)

Thanks Jeff, the problem is that the colors are repeated 10 times, or for as long as he is seeing that color. the ideal is for the color to be said only once, regardless of the time he has been seeing the color
Code:

colorLeft = ColorSensor(INPUT_2)
print(colorLeft.reflected_light_intensity)

tank_drive.on_for_rotations(SpeedPercent(20),SpeedPercent(20),1)

while True:
intensity_left = colorLeft.reflected_light_intensity
tank_drive.on(SpeedPercent(20), SpeedPercent(20))

print(intensity_left)


if (colorLeft.rgb[0]==255 and colorLeft.rgb[1]==0 and colorLeft.rgb[2]==0):
    print( 'Red' )
    say('Red')
    
if (colorLeft.rgb[0]==0 and colorLeft.rgb[1]==255 and colorLeft.rgb[2]==0):
    print( 'Green' )
    say("Green")
    
if (colorLeft.rgb[0]==0 and colorLeft.rgb[1]==0 and colorLeft.rgb[2]==255):
    print( 'Blue' )
    say("Blue")
    
if (colorLeft.rgb[0]==0 and colorLeft.rgb[1]==255 and colorLeft.rgb[2]==255):
    print( 'Turquoise')
    say("Turquoise")
    
if (colorLeft.rgb[0]==255 and colorLeft.rgb[1]==0 and colorLeft.rgb[2]==255):
    print( 'Pink' )
    say("Pink")
    
if (colorLeft.rgb[0]==255 and colorLeft.rgb[1]==255 and colorLeft.rgb[2]==0):
    print( 'Yellow' )
    say("Yellow")
    
if (colorLeft.rgb[0]==0 and colorLeft.rgb[1]==0 and colorLeft.rgb[2]==0):
    print( 'Black' )
    say("Black")


if (colorLeft.rgb[0]==255 and colorLeft.rgb[1]==255 and colorLeft.rgb[2]==255):
    print( 'White' )
    say("White")
    break

say(“Stopping”)

That is exactly what Jeff proposed you a solution for. The basic idea is that you need to keep a state variable containing the previously read colour - for example last_colour and then print the coulour only if it changes from the previous state. Do you have ideas how to implement that with your code?

Some comments for your code:

  • Are you sure you want to detect only the very extreme values of the RGB components (0 and 255)? What if you read a slightly different value like 1 or 254?
  • The program contains a lot of repeated code. Try to limit the repetition. You can start by creating a function which given the RGB components would return one of the colour names.

Please, in your posts in this forum enclose the code between triple backticks like this:

```
Your code will be here
```

This prevents mangling of the code by treating it as Markdown.

1 Like

Edit: Sorry, I should’ve read this first:
Color Sensor — pybricks v3.2.0b1-r3 documentation . In that, it seems to use HSV rather than RGB colours. That would be easier when comparing colours.

@Morenado : if you create a function as @vbrozik suggests, and put your if-statements in it, then your code would look a lot like my guess at your code. (It would be the get_colour() in what I posted.)

Edit: However, I think it is still true that …
I would say the main problem is that you only read the sensor once, outside the loop. You need to read it each time round the loop to see if the colour has changed.
That is, you need to call colorLeft.color() as in the documentation.

Václav’s observation about the problem of expecting an exact match to the saturated colour values is good advice too. If the sensor is something like a camera, it could come up with all sorts of mixtures, so really you should ask which ideal colour it is nearest, and white if it is not close enough to any. That can be a bit messy to code, but easier inside a function.

Then in your loop you’re going to call it like:

colorLeft = ColorSensor(INPUT_2)

while True:
    tank_drive.on(SpeedPercent(20), SpeedPercent(20))

    colour = get_colour(colorLeft.color())   # <-- !

    if colour == last_colour:
        time.sleep(0.5)
    else:
        print(colour)
        say(colour)
        last_colour = colour

Again, I haven’t tried any of this, so there may be silly mistakes.