New GoPiGo Pi B+ Dexter Raspbian Speed Difference with Older GoPiGo Pi B

We are publishing our code and tutorials at www.github.com/itinstructor/wnccnasa

1 Like

Are there “find the bugs” in motors.py?

2 Likes

I am not sure what you mean, they all work. I was working on them this afternoon, and finished testing them all a bit ago.

2 Likes

I saw two suspicious statements and didn’t want to spoil if they were intentional:

Motors.py

  • Lines 67 vs 68
  • Lines 70 vs 71

BTW, there are some new orbit commands in the API that are pretty cool also.

2 Likes

That was a mistake, it was supposed to print 180.
I did add in an orbit, it is pretty nice!

2 Likes

I didn’t look over those. Will students ever use multi-threading, multi-processing, or multiple programs accessing the same sensor, or accessing the I2C bus?

The EasyGoPiGo() class defaults use_mutex = False. I believe this to be a philosophical error to not use the protection mutex in preference to speed. I believe in optimizing only if and where needed, and always coding for errors/exceptions/conflicts/edges from the start. Thus, suggest all instances be created with use_mutex=True, which will get passed down to sensor instantiation where important.

2 Likes

You might find this interesting:

2 Likes

I don’t think so. I can get them up to accessing the sensors while doing something else. I am going to try to get them up to multi-threading.
I appreciate the info on use_mutex=True. I haven’t dug that far into the API or know enough yet to quite understand how mutex relates to multithreading. Always something more to learn!

2 Likes

DI implemented optional mutex protection around the I2C bus to prevent multiple threads or processes accessing the bus at the same time. If egpg=EasyGoPiGo3(“use_mutex=True”) was declared in each egpg object when instantiated, then the process or thread that wants to access a sensor via the bus, either acquires the mutex or waits until it acquires the mutex, so that only one process at a time will be sending commands across the bus.

The concept of a single resource with multiple users becomes important when complex programs get broken up into smaller independent programs, beyond the I2C bus also. On my robot I have an independant health check program that instantiates an EasyGoPiGo3() object to check the battery and perform a system shutdown if the battery level falls to low. This way, I don’t have to write battery level checks into every single program I write for the bot.

BUT - every instantiation of the EasyGoPiGo3() class performs a set_speed(300) under the covers. This can set up a race condition of who started when. My “juicer” program that puts the bot back on the dock wants the speed set at 150DPS for most accurate turns. If juicer starts first, resets the speed to 150DPS, and then “thinks” the speed will not change, it will not know that the healthcheck program starting is going to set the speed back to 300 DPS.

This last case is not solved by mutex, but illustrates some of the complexities of multiple processes accessing a single resource (the GoPiGo3 red board in this case).

One of the most difficult transitions in my programming career was to stop thinking linear execution of software. Today with every processor having multiple cores and algorithms so complex that execution gets farmed out across multiple cores in nets or graphics, avoiding linear thinking is a must.

Just a thought.

2 Likes

Along the lines of a first look at threading - an exercise could adapt the following “WiFi LED Blinker” excerpt to dex_eyes.py for the eyes. (I have disabled antenna_wifi.service so that I can use the WiFi LED, but the concept works for the “Eyes” as well.)

import threading

WHITE_BRIGHT = (255, 255, 255) # color 0
RED = (255, 0, 0)            # color 1
ORANGE = (255, 125, 0)       # color 2
YELLOW = (255, 255, 0)       # color 3
YELLOW_GREEN = (125, 255, 0) # color 4
GREEN  = (0, 255, 0)         # color 5
TURQUOISE = (0, 255, 125)    # color 6
CYAN = (0, 255, 255)         # color 7 light blue
CYAN_BLUE = (0, 125, 255)    # color 8 
BLUE = (0, 0, 255)           # color 9
VIOLET = (125, 0, 255)       # color 10
MAGENTA = (255, 0, 255)      # color 11
MAGENTA_RED = (255, 0, 125)  # color 12
COLOR_LIST = [WHITE_BRIGHT, RED, ORANGE, YELLOW, YELLOW_GREEN, GREEN, TURQUOISE, CYAN, CYAN_BLUE, BLUE, VIOLET, MAGENTA, MAGENTA_RED]


def do_wifi_blinking(egpg,color=RED):
	global wifi_blinker_thread_quit
	try:
		r,g,b = color
		while wifi_blinker_thread_quit is not True:
			egpg.set_led(egpg.LED_WIFI,r,g,b)
			sleep(1)
			egpg.set_led(egpg.LED_WIFI,0,0,0)
			sleep(1)
	except Exception as e:
		print("do_wifi_blinking: Exception {}".format(str(e)))
		raise e
	# print("do_wifi_blinking() exiting")
	wifi_blinker_thread_quit = False

wifi_blinker_thread = None
wifi_blinker_thread_quit = False

def wifi_blinker_on(egpg,color=RED):
	global wifi_blinker_thread,wifi_blinker_thread_quit

	if wifi_blinker_thread:
		pass
	else:   # need to start thread
		wifi_blinker_thread_quit = False
		wifi_blinker_thread = threading.Thread(target=do_wifi_blinking, args=(egpg,color,), daemon=True)
		wifi_blinker_thread.start()

def wifi_blinker_off(egpg):
	global wifi_blinker_thread,wifi_blinker_thread_quit

	if wifi_blinker_thread:
		wifi_blinker_thread_quit = True	# tell thread to quit
		# wifi_blinker_thread.join()	# wait for thread to quit
		timer = 0
		while wifi_blinker_thread_quit and (timer < 5):
			sleep(1)
			timer+=1
		wifi_blinker_thread_quit = False
		wifi_blinker_thread = None
	else:
		pass

You’ve got a lot on your plate with teaching - I’m sorry for going on here. What you have done looks great. Glad you have chosen GoPiGo3 to be a part of your pedagogy.

2 Likes

Very nice, I appreciate it. You will probably see a version of this appearing in our github site at some point.
Do you have a github for your code?
Thanks again!

2 Likes

I would call that a bug/design flaw.

BTW, technically that’s not a “race condition” since it can be temporally distant.  However it does illustrate the kind of conflict that can happen when a class/method doesn’t respect that other instances or classes may have changed something.

Is it possible to query the current set speed?

It sounds like there needs to be some kind of “dirty” flag, (killroy_was_here = TRUE), to indicate that it has already been initialized so that subsequent instantiations don’t reset it.

Can classes have privately global flags/variables?  That is, something local to the class that can be set and read by any instance of the class?

You can access the eyes directly within the easygopigo class.

@cyclicalobsessive had to jump through hoops to mess with the antenna LED because it’s dedicated to a different use.

Another tid-bit:

The three signal lines to the on-board neopixels are brought out to pads on the PCB so you can actually add neopixel LEDs if you want!  I haven’t tried this, (yet!), but it should be possible to address them by simply incrementing the LED address.

2 Likes

Yes, github serves as a backup for Carl, Dave, DeskPi, and the ROS2 Ubuntu VM I run on my Mac.

Carl’s repository contains some notable stuff:

  • /plib contains all his operational code
  • /Examples/threads compares Python 3.7 threading vs multi-processing for i/o or cpu bound ops
  • /Examples/pycam motion detect, several streaming techniques
  • /Examples/classVars test if Python class variables are available across multiple processes (hint no)
  • /Projects/LogLightValueAndPlot uses the picamera to sample room light levels over time and plot the logged levels
  • /Projects/raspberry_pi_sound_meter_and_plot uses a microphone to sample noise levels over time
    and plot the logged levels
  • /Projects/easyPiCamSensor Offers PiCam as four sensors: light intensity, color, motion, camera
  • /Projects/servoscan and scan360 perform distance sensor scans and plot to a terminal window. I never got around to doing a windowed plot for desktop use b/c most of my dev is remote shell terminal

and there are some unfinished, dead end stuff to avoid all over the place.

Carl’s /systests contains test programs I have written to test every subsystem from processor, motors, encoders, sound, you name it there is probably a test - the most useful:

  • motors/wheelDiaDriveTest.py allows trying various wheel diameters to find most accurate
  • motors/wheelBaseRotateTest.py allows trying various wheel base values for most accurate turns
2 Likes

I am sure glad I posted to this forum. I am learning all sorts of good things.
I have Raspberry Pi Cameras, IR cameras, and a couple of piCams to experiment with.
So little time, so many toys . . .
Thanks for the github address, there is a lot of interesting code and shell scripts to look through. I will keep you posted on my progress.

3 Likes

Just a quick note because it’s Thanksgiving for me today.
Gopigo OS is now an open platform and allows you to connect to the normal Raspberry Pi desktop where you can code with whatever languages and editors that strike your fancy.

You start with an wifi access point but you can switch to your normal network and make that permanent if you prefer.

3 Likes

Happy Thanksgiving!
/K

2 Likes

Happy Thanksgiving!

Do you eat turkey on Thanksgiving or maybe moose? :wink:

Ahhh!&nbsp: I can smell it now - stuffed moose with all the trimmings!

1 Like

One of the things that I like about the new GoPiGo OS is that I can program in Python and flip over to Bloxter to try something out.

One caveat:
GoPiGo OS only works with the GoPiGo-3 - the red-board GoPiGo.

Another thing:
@cyclicalobsessive mentioned that the last “supported” version of Raspbian for Robots was the Stretch version, though Buster is also well supported - and that the majority of the effort has gone into GoPiGo OS.

I cannot say that this is the new policy for MR with respect to the GoPiGo, but it makes sense to me.

  1. There’s only one platform to support.  This is a significant consideration especially if staff is limited and there’s a lot to go around.

  2. There are subtle differences between the old Dexter OS and Raspbian for Robots - and the transition between them isn’t always smooth or easy.

  3. (AFAIK) GoPiGo OS is designed to bridge that gap - starting off as a simple scratch-like programming environment, (based on EduBlocks), that can transition to a full-bore development platform like Raspbian for Robots.

Once my hardware stuff is done, I am going to start transitioning away from R4R to a purely GoPiGo OS environment to test that theory.

@cleoqc, is this correct?  Should I report discrepancies?  (i.e.  This works in R4R, but not in GoPiGo OS?)

1 Like

Everything should work for either OS, so yes, if there are discrepancies, please report them.

Nitpicking: Bloxter is not based on Edublocks, but on Google blockly.

2 Likes

I received a nice reply from Modular Robotics.
Nicole Parrot (Modular Robotics)

Oct 12, 2021, 10:18 AM MDT

Hello William,

We did get a batch of GoPiGos with 16 tick motors. A software fix was applied on GoPiGo OS, and if you do an installation on Raspberry Pi OS.

We are slowly moving away from Raspbian for Robots, favouring instead direct installs on Raspberry Pi OS, or using GoPiGo OS. Raspbian for Robots was created years ago because the official os at the time was sorely lacking. However this is no longer the case. Raspberry Pi OS now comes with a VNC server, a method to boot up the Pi completely headless, including on the first boot and an easy method to change the hostname.
You can install the full suite of GoPiGo libraries and tools on Raspberry Pi OS using the following commands:

curl -kL dexterindustries.com/update_gopigo3 | bash
curl -kL dexterindustries.com/update_sensors | bash

At the other end of the sprectrum, GoPiGo OS - as opposed to Dexter OS - is now a fully open platform. You have a wifi access point for ease of access, but you can still log into the desktop via VNC or SSH. And if you want to connect the robot to your surrounding wifi, you can too.

I’m sorry for the f-strings, that’s all on me. I like f-strings and since both GoPiGo OS and the latest Raspberry Pi OS support them, I just went ahead. Obviously I didn’t consider the possibility of people updating on previous versions. I’ll remove the f-strings.

Nicole,
ModRobotics Engineer

3 Likes