Xan's Phoenix code in C running on Bap28

Quick update…

Updated xbee code to go along with other xbee packet conversions. Disabled HSERVO code in phoenix code to make it walk OK. Fixed a few bugs…
CPhoenix with Lib.zip (96.7 KB)

Hi Kurt,

I also independently decided to port Xan’s code into C. I am using it on an STM32 Arm processor. Everything has worked great so far . . . except for balance mode.

I have a problem similar to the one you described. When I enter debug mode and run through one cycle of the kinematics calculations with Balance mode on, the legs seem to want to curl up. Actually, I’ve tracked it down to the TotalYBal calculations. No matter which gate I use when walking, the TotalYBal calculation never results in 0. With each step of the gate, the TotalYBal variable takes on values of either +60 or -60. This makes the legs flail about wildly as they try to rotate the body. :open_mouth:

I’ve compared our code. I use the same length balance mode variables. You used one more degree of precision in BalCalcOneLeg() and BalanceBody(), so I changed my code to match yours. You also casted all of the fixed point math to float. I also did that . . . the behavior was the same. Do you have any other ideas as to what could be going wrong?

Thanks!
-Dan

Hi Dan,

Sorry I am not sure how much I can help. I am not sure if mine is100% either. I know I need to run through and do some more thorough testing. That is probably to take a basic version and run it through a standard gait or two and record lots of data, like where each servo is being driven to.

Then do the same again with the C code. Some of the problems I ran into is that with Basic all of the calculations are done in 32 bits, whereas in C the precision of calculations are done depending on the sizes of the variables involved. That is why you will see a lot of casts to 32 bits.

Kurt

I’m interested in a C code solution as well. I last worked on code from CH3-R. Several places there were “work-arounds” for Basic bugs. But I think those bugs are long gone now.

Alan KM6VV

I have not had a chance to play much with fixing the problem with balance mode. But I found an issue in the code that may be causing or related to issue. The problem is in the function Gait. The last big if statment in that function in one place when I converted the code from basic to C, I did not change a & to && so it was doing a bitwise and versus a logical and. Also I changed the if to put a set of Perens around the compare for safe measures. The function now looks like:

[code]//[GAIT]
void Gait (byte GaitCurrentLegNr)
{

//Check if the Gait is in motion
GaitInMotion = ((iabs(TravelLengthX)>cTravelDeadZone) || (iabs(TravelLengthZ)>cTravelDeadZone) || (iabs(TravelRotationY)>cTravelDeadZone));

//Clear values under the cTravelDeadZone
if (GaitInMotion==0)
{	
	TravelLengthX=0;
	TravelLengthZ=0;
	TravelRotationY=0;
}

//Leg middle up position
//Gait in motion														  Gait NOT in motion, return to home position
if ( (GaitInMotion && (NrLiftedPos==1 || NrLiftedPos==3) && GaitStep==GaitLegNr[GaitCurrentLegNr])  
	|| ( !GaitInMotion && GaitStep==GaitLegNr[GaitCurrentLegNr] && 
			((iabs(GaitPosX[GaitCurrentLegNr])>2) || (iabs(GaitPosZ[GaitCurrentLegNr])>2) || (iabs(GaitRotY[GaitCurrentLegNr])>2)) ))			//Up
{
	GaitPosX[GaitCurrentLegNr] = 0;
	GaitPosY[GaitCurrentLegNr] = -LegLiftHeight;
	GaitPosZ[GaitCurrentLegNr] = 0;
	GaitRotY[GaitCurrentLegNr] = 0;
}		
else
{
	//Optional Half heigth Rear
	if ( ((NrLiftedPos==2 && GaitStep==GaitLegNr[GaitCurrentLegNr]) 	//+2
			|| (NrLiftedPos==3 && (GaitStep==(GaitLegNr[GaitCurrentLegNr]-1) || GaitStep == (GaitLegNr[GaitCurrentLegNr]+(StepsInGait-1)) )))
			 && GaitInMotion)
	{				
		GaitPosX[GaitCurrentLegNr] = -TravelLengthX/2;
	  	GaitPosY[GaitCurrentLegNr] = -LegLiftHeight/(HalfLiftHeigth+1);
		GaitPosZ[GaitCurrentLegNr] = -TravelLengthZ/2;
	  	GaitRotY[GaitCurrentLegNr] = -TravelRotationY/2;
	}
	  
	else
	{

		//Optional half heigth front
		if (  (NrLiftedPos>=2) && (
				(GaitStep==(GaitLegNr[GaitCurrentLegNr]+1) || (GaitStep==(GaitLegNr[GaitCurrentLegNr]-(StepsInGait-1))) )) && 
				GaitInMotion) 
		{		
			GaitPosX[GaitCurrentLegNr] = TravelLengthX/2;
			GaitPosY[GaitCurrentLegNr] = -LegLiftHeight/(HalfLiftHeigth+1);
			GaitPosZ[GaitCurrentLegNr] = TravelLengthZ/2;
			GaitRotY[GaitCurrentLegNr] = TravelRotationY/2;
		}
		else  	  
		{

			//Leg front down position
			if ((GaitStep==(GaitLegNr[GaitCurrentLegNr]+NrLiftedPos) 
					|| GaitStep==(GaitLegNr[GaitCurrentLegNr]-(StepsInGait-NrLiftedPos))) && (GaitPosY[GaitCurrentLegNr]<0) )
			{
  				GaitPosX[GaitCurrentLegNr] = TravelLengthX/2;
  				GaitPosZ[GaitCurrentLegNr] = TravelLengthZ/2;
  				GaitRotY[GaitCurrentLegNr] = TravelRotationY/2;      	
  				GaitPosY[GaitCurrentLegNr] = 0;	//Only move leg down at once if terrain adaption is turned off
			}
			//Move body forward      
			else
			{
  				GaitPosX[GaitCurrentLegNr] = GaitPosX[GaitCurrentLegNr] - (TravelLengthX/TLDivFactor)     ;
  				GaitPosY[GaitCurrentLegNr] = 0  ;
  				GaitPosZ[GaitCurrentLegNr] = GaitPosZ[GaitCurrentLegNr] - (TravelLengthZ/TLDivFactor);
  				GaitRotY[GaitCurrentLegNr] = GaitRotY[GaitCurrentLegNr] - (TravelRotationY/TLDivFactor);
  			}
		}
	}
}
//Advance to the next step
if (LastLeg)	//The last leg in this step
{
	GaitStep = GaitStep+1;
	if (GaitStep>StepsInGait)
		GaitStep = 1;
}

} [/code]
Again I have not been able to test this yet. I need to put a BAP28 back on one of my Hexs to do so…

Kurt

Thanks for the help Kurt! I’ll give it a try!

I have been doing some playing around with my C/C++ code for the phoenix as well as the underlying library code. There is still tons of stuff to do, but I have some stuff now in the library to make it easier to port Arduino code. I have changed my PS2 code to use a C++ library that Bill Porter wrote for the Arduino and ported that library over to my C code. I have also done some work to make it such that I can build the main C/C++ library and have it build a library for the Bap28 in addition to another library for the Bap40. The Bap40 version has finally now had some testing and things like both hardware serial ports are working… I then built my phoenix code for both the 28 and the 40 and lots of it appear to be working on both. So I reconnected a 28 to my CHR-3 and now can control it with either the PS2 or the DIY control. You can configure it to have both. This is not even an alpha version of the libraries, but then again it is just for my own fun!

I thought I would put a drop up here to see if any one wants to take a look, before I make some more major changes, like: Convert my hardware serial functions from the old hserin/hserin2 type functions, to the new ones that are likely coming in a release soon, which is more like: hserin(1, …) and hserin(2,…) for the different hardware ports. That way if they come out with a bap with 3 ports they don’t have to add yet more commands. Yeah!!! Also soon will try testing on Arc32 and add some support for pins not connected to normal IO ports.

Then finish debugging my hservo support…

Then maybe some document that lets someone else know what you need to do to build the library - like you need to have nmake on your system, and use a command prompt to issue the nmake… Sorry but Studio currently has no support for libraries.

Then to use the library, you need to edit the proj…xlc file to add a reference to the library. As shown in my phoenix versions

Then you need to muck with how the interrupts are setup with the files (regdefs.h - I mucked with so I can use the better H8 header files, plus hacked to handle multiple platforms) (vects.c - Tried to add a little stuff to figure out why an app faulted), interrupts.c - needed to muck up to point to functions within the library…

That is all for now.

Kurt

P.S. - Bob - Some more fixes went in since I sent you a drop. Things like PS2 working, TImer working better…
CPhoenix with Arduinosh lib.zip (141 KB)

Kurt,

Haven’t had a chance to check it out, but are you making multiple libraries, like BAP28.LIB, BAP40.LIB…? Or using the same name?

Anyway, sounds great. 'Hope to get time to check it out!

Alan KM6VV

I am creating two different libraries bap28sup.a and bap40sup.a - I maybe should rename them to something like:
bap3694.a and bap3687.lib, but…

Kurt

They both work, although I tend to think more in the uP domain.

did you use 1.0.0.35 to compile?

Alan KM6VV

I think so. I know I installed it, but the about shows .33 (but then again their copyright shows 2009).

Kurt

Then it didn’t install correctly. 1.0.0.35 shows 1.0.0.35 in the about window. Also copyrights are from the date forward. So we could technically put a copyright of 1999 on our software that has even a little bit of code form way back then. You can also state a copyright of multiple years for each peice of code that is from a different year. We made a fresh start with Studio in 2009 so thats the copyright date we went with.

Thanks Nathan, my machine did some form of rollback a day or so maybe it went back to some earlier version. I will install again later today or so, unless I hear you have a new one coming…

Everyone else, I updated my hardware serial code to the newer form that looks something like: hserout(1, …) for the first port and hserout(2, … for the second port if there is one). Changed the test program and my wrappers and my printf functions to reflect this.

Also note: in the phoenix_… directory, the globals.h has defines for which processor you are building for. I do this automatically in the make files for the library.

So was I.

OK, I’m doing something wrong again with these projects. (I looked for the last explanation (probably for Jonny’s code), but couldn’t find it.

I just tried on another machine with a slightly older (but working) .32, to no avail. I now see part of the problem. I didn’t un-zip with directories.

But now the compiler is looking for:

C:\Users\Kurt\Desktop… bap28sup.a

That might imply that I should build the library first, but I really don’t want all that path clear back to users.

Thanks,

Alan KM6VV

Hi alan,

I uninstalled 33 and installed 35 again and it now shows 35 :smiley: I have also been able to build the stuff.

Yes you need to build the library first. Yep my .xlc file had the hard coded path.
From project364.xld I have:


OUTPUT_ARCH(h8300h)
ENTRY(_start)
INPUT(C:\Users\Kurt\Desktop\LynxMotion\C-Projects\BAPLib\bap28sup.a)
INPUT(C:\PROGRA~1\BASICM~1\BASICM~1\H8300-~1\bin\..\lib\gcc-lib\h8300-coff\3.2-GNUH8_v0301\..\..\..\..\h8300-coff\lib\h8300h/normal\libstdc++.a)
INPUT (C:\PROGRA~1\BASICM~1\BASICM~1\H8300-~1\bin\..\lib\gcc-lib\h8300-coff\3.2-GNUH8_v0301\..\..\..\..\h8300-coff\lib\h8300h/normal\libm.a)
INPUT (C:\PROGRA~1\BASICM~1\BASICM~1\H8300-~1\bin\..\lib\gcc-lib\h8300-coff\3.2-GNUH8_v0301\h8300h/normal\libgcc.a)
INPUT (C:\PROGRA~1\BASICM~1\BASICM~1\H8300-~1\bin\..\lib\gcc-lib\h8300-coff\3.2-GNUH8_v0301\..\..\..\..\h8300-coff\lib\h8300h/normal\libg.a)
INPUT (C:\PROGRA~1\BASICM~1\BASICM~1\H8300-~1\bin\..\lib\gcc-lib\h8300-coff\3.2-GNUH8_v0301\..\..\..\..\h8300-coff\lib\h8300h/normal\libc.a)
INPUT (C:\PROGRA~1\BASICM~1\BASICM~1\H8300-~1\bin\..\lib\gcc-lib\h8300-coff\3.2-GNUH8_v0301\h8300h/normal\libgcc.a)

Obviously this should be updated to not point directly to where it is on my machine…

I wish there was some clean way to set project specific libraries, but I have never had any luck in Studio finding any libraries I specify in the tools\preferences (C/C++ tab) to be loaded, so I ended up editing the linker script files (.xlc)

As I mentioned in the earlier email, I use an NMAKE makefile to build the program from a Command prompt. I have a project defined for the cod to make it easier to edit, but currently there is no ability within studio to create a library. Nor is there any clean way to add commands to the tools menu, as the working directory is either hard coded or it is off to some random location. Also even if there were a way to get the proper working directory, there is no mechanism in place to be able to capture the output from the command and show it in some window like the build window. Hopefully BM will get a chance to enhance their abilities here.

To use the makefile to build the libraries, I use nmake, which I downloaded from Microsoft. Also to make the makefile work I believe that you will need to update your path environment variable to find nmake as well as to H8’s version of the GCC tools.

The way I do that on my machine (Windows 7 similar Vista), is go to the start menu, and right click on the Computer item in the start menu. From there choose properties, From the properties window, choose the Advanced system settings link, In the property window that is popped up, click on the environment variables button. Then go to the system variables list and double click on the environment variable: Path. In the variable value field, I have added: ;C:\Program Files\BasicMicro\Basic Micro Studio\h8300-coff\bin;C:\Program Files\BasicMicro\Basic Micro Studio\h8300-coff\h8300-coff\bin

I hope the helps.

Kurt

Hi Kurt,

OK, I should have realized that. You are using the GCC tool chain, and BM isn’t able to support that.

I missed the point earlier about NMAKE and all. I’ll give it a try when I get a chance. Right now, I’m concentrating on getting both the 'Quad and the MicroMoose running (so neither are working), so I’m not wanting to tackle another large task.

Thanks!

Alan

Quick update: I have updated the Arc32 pin table to the information from Nathan. I also have implemented a version of HSERVO2 type code for the Arc32, which is starting to work. I have both the pulse generation working on some pins as well as the group move type code. This also is needing some tweaks. I am still debugging some issues on the higher pin numbers where I am getting some strange pulses on pins I have not told to do anything. The pins I have seen it on include: 22, 23, 29,30,31.

The code currently generates an interrupt on every Timerz0 overflow. This happens every 65536 instructions or 3.27ms. I am setting up the cod to have a servo cycle on every 6 of these counts or: 19.67ms which is probably close enough for the servos. There are 4 channels associated with the chips driving the servos with 8 servos per channel. The channels are connected to IO pins associated with TimerZ and automatically drive these signals when we get timer compare matches on GRA-GRD on TimerZ0/Z1. I generate an interrupt when the compare match happens, such that I can set the new GRx timer values for when we want the pulse to go low. I don’t interrupt on the go low as the overflow of Z0 will setup the new GRx values. For those servos that have real H8 IO pins connected to them, before I switch the Channel to the next group of 8 servos, I set the H8 IO pin to low. This should hopefully handle the digital servo issue… (I hope).

The code still needs lots of cleaning up. I hate how in the Timerz0 overflow I more or less replicated the same code 8 times. Will maybe table drive it. Also it is hacked in with how I use this implementation instead of a more standard servo implement ion (which also still needs lots of work). But I decided to upload the current stuff in case anyone does wish to play…

Kurt

Real quick and dirty update. I think the hservo2 stuff is working now.

Problem was I init the output lines for the timer pins to be ouput. Should be input as when we are not using that pin (set change to 0) we want the value to float such that it does not set an actual value on the pins connected to that group…

Kurt

Another real quick and dirty update. I will be busy with some non computer/robot projects for a little bit so I thought I would post a slightly updated version, also with a first pass of the phoenix code that I ported to C now running on Arc32 with my own HServo code. I took my Arc32 phoenix (no SSC-32) that I had my basic version running and simply downloaded the C version without changing any hardware…

It does walk and move. Not smooth yet, some servos doing something weird at times. I already found a few times that I had debug code that toggled an IO line that screwed some up. Will investigate later. Also not sure if PS2 is working yet. Mine stopped working on my arc32, again will investigate later. Probably a loose wire… I have not ported over my Arc32 support that I did in basic for emulating and downloading sequences yet…
Will also investigate possible performance issues. Things like I probably have both TimerB1 and TimerZ updating timer counts when when in HServo2 mode could use that one… Lots of work(play) left to do, but I am happy that it talked some to XBee, debug messages working and it is showing signs of walking…

Kurt
CPhoenix with Arduinosh lib.zip (194 KB)

Replicates 8 times? I think I know what you mean. Either use a state machine, or possibly a table.

You might also make this “frame time” basic to your System timing. Each individual servo update window becomes a “slice” Do some tasks in one slice, some in another.

I can really appreciate your efforts!

Alan KM6VV