FRC1076 / RobotKitLib

Robotpy-WPILIB equivalent for raspberry pi robot kit
1 stars 1 forks source link

Use two rear Neopixel lights to signal if the robot is enabled (green) or disabled (red) #7

Open mcolinj opened 3 years ago

mcolinj commented 3 years ago

Check out the Freenove example code and AdaFruit Neopixel code to see how you can do this. After you've figured out how to turn those particular lights on and the correct color, create a library component that manages the lights. Give it an enable/disable method that will do the right thing.

mcolinj commented 3 years ago

Note that enable/disable is really a function of the "field" (e.g. run.py). So the light might be tied to state that the field knows about. That has to somehow be communicated to the robot (perhaps a robot method that the field could call to let the robot know that it has been disabled/enabled). Just thinking out loud here.

mcolinj commented 3 years ago

FYI, you can find the Freenove code for controlling the lights (running light shows) here:

https://github.com/Freenove/Freenove_4WD_Smart_Car_Kit_for_Raspberry_Pi/blob/master/Code/Server/Led.py

once your robot is built, you can run some of that code directly using the test.py program on the server:

sudo python3 test.py Led

would run the Led test program. Look at the Led section of the test.py to see what it does. You can, of course, clone that repository and hack on the code all you want.

MrRSquared commented 3 years ago

Hello, I love this project and want to reach out and help where I can (which may not be much). If at any time, I overstep, please let me know. The Freenove code uses a Color function that declares a Color object. It was difficult for me to find its definition (I had to ask their support, and still do not know where it is defined in the code). Here is the function.

def Color(red, green, blue, white = 0):
        """Convert the provided red, green, blue color to a 24 bit color value.
        Each color component should be a value 0-255 where 0 is the lowest intensity
        and 255 is the highest intensity.
        """
        return (white << 24) | (red << 16)|(green << 8)| blue

matthew's note: Hi, Mr. R-R. You are welcome to help. Of course, we like the students to do as much as they can. This kind of hint is good information, since it can help them get unstuck. Ryan just got his robot kit a few days ago, so I'm hopeful he will be able to get things rolling soon.

Mr R-R's note: Thank you. This is such a wonderful project and I am learning a lot about teaching programming (something I am learning with the team) from reading these discussions. These students are doing an excellent job with this project.

One other thing to note that could be helpful is that I think the Adafruit library (and by extension the FreeNove) needs to run with superuser permissions on the pi in order to work.

mcolinj commented 3 years ago

More comments here on how I think this might be used (in wpilib kind of way). If we think of the NeoPixel string (of 8 LEDs) as just a number of connected LEDs that are available with indices 0-7, then they could be claimed by different users for their (mostly) exclusive use. Keeping in mind that I have not discovered which is which. (I'll leave that up to the programmer) We'll need something like this:

robotConfig
    RIGHT_FRONT_NEOLED = 0
    LEFT_FRONT_NEOLED = 1

def robotInit(self):
    self.right_front_led = NeoLed(RobotConfig.RIGHT_FRONT_LED)
    self.left_front_led = NeoLed(RobotConfig.LEFT_FRONT_LED)

    self.vision_system(VISION_LISTEN_PORT, self.left_front_led, self.right_front_led)

And then the vision system has a couple of indicator lights so the somewhere after we have received the latest target report, it has logic like this:

if angle_to_target > 0:        #     target is off to the right
       self.reportAngleToPIDController()
       self.right_indicator.red()
       self.left_indicator.off()
else:
       # the other way around

We could, of course, think about whether or not the vision subsystem needs to know anything about Neopixels, and just thinks it has an anycolor LED, in which case it could just choose to turn it on/off. This means that we might want to try to have a special variant of a NeoLed that has the color choosen at creation time, and then only turns on or off.

e.g.

led = NeoMonoLed(Color(100,  0, 0), RobotConfig.RIGHT_CENTER_FRONT_LED)

This would create an interface to the RIGHT_CENTER_FRONT_LED led with only on() off(), and red color.

What I like about the single pixel approach is that it makes each light into a resource that can be used on the robot by different subsystems. Can be a nice diagnostic tool. Color could even be used to indicate general quantitative/qualitative values. Is a certain servo running (forward/backward/faster/slower), is a sensor indicating a value (higher/lower), etc... $100 Motor controllers have such indicator lights, so we can fancy things up with our own.

Of course, everyone likes a nice light show, so while in different modes, we could display something more like light shows using all of the lights. For example, before the robot connects to the driverstation, run.py could play the "breathe" light show which is just brightness on a sine wave with breathing frequency. About 12-15 cycles per minute. (e.g. .25Hz)

For brown-out events (low voltage indication), we could flash all of the lights for example, wresting control away from other users of the lights. That kind of coordinating is a nice project in and of itself, as it might require that the clients of the light services would be assigned priorities, and then the lighting control would have to respect those priorities when deciding who could get control. But that is pretty advanced, and, we are more interested in making immediate progress in making the individual lights available. We can always add more complexity. For now, we can start with individual lights with a simple interface and then go from there.