Hi, Enjoy! -Edward]]>

Hi,

Enjoy!

-Edward

]]>

In this post I will be explaining the Logo Sumo fight program. This program is running on a MarkIII robot that was adapted to run the LogoChip.

My comments will be in red.

The Logochip has two start programs. One called powerup that always gets called on powerup, and one that is called startup that is called when the start/stop button is pushed. When the start button is pushed the fight program gets called.

to startup fight end

All sensors return a value from 0 to 1000.

For the eye sensors, 1000 means that something is immediatly in front of you. Less than 100 usually means nothing is in front of you, or to far for you to see.

detectlevel is the level that the robot decides that something is in front of you. Values from 200 to 1000 give an estimate as to distance away from you.

For the nose sensors 1000 means you are seeing all black, 0 would be all white. This is how we look for the boundary electrical black tape indicator on the floor.

;* ;****************************************************************************** ; GLOBAL VARIABLES ;******************************************************************************* constants [ [detectlevel 200] ] global [ walkerror walkcount frame_count sniff_leftcounter sniff_middlecounter sniff_rightcounter sniffright sniffleft sniffmiddle

walkerror lets us know if we encountered a line on the floor, walkcount holds the number of steps that we have left to travel. Positive steps mean forwards and negative steps mean backwards. framecount holds the current frame count number. This fight program is constantly accumulating sensor values in several running counts. After a frame of 32 samples, we divide all of the running counts by 32. This gives us a good average for the sensor values. This typically represents what the sensor saw in a 32ms frame. A frame length is dependant on the amount of time it takes to return to that section of code. Please note that I used 1ms as an example.

If we did not do this, then instant glitches on a sensor would confuse the robot. Therefore, we are averaging all of the sensor inputs in frames of 32.

sniff_leftcounter holds the running average for a 32 sample frame, sniffleft is a variable that will hold the averaged value. The checksensors function is the one that is in charge of updating all of the sensor variables. You will see checksensors being called in the main fight loop.

eye_leftcounter eye_rightcounter eyediff eyeavg lefteye righteye scanmode scan_lr walkholdoff veerangle ] ;******************************************************************************* ; MAIN ROUTINE ;******************************************************************************* to fight resetvariables loop [ checktimer checksensors setwalkerror checkwalk think ] end

The fight program is the main code that executes in a never ending loop. We first reset all of the variables before entering the loop. We then enter the loop.

In the loop we checktimer to see if we need to roll over the system timer. I wanted control of this event so the system timer does not roll over when I am in the middle of counting frames.

Next we check all of the sensors and update the global variables, if we have accumulated 32 samples.

Checkwalk will check the global walk variables and move the robot while checking for boundary conditions. checkwalk returns an error that is assigned to the setwalkerror global.

The next function is think. This is where the robots decision making process is done.

to think ;check walk error (am i out of bounds) ; if (walkerror = 1) [ ;going forwards if (walkcount > 0) [

At this point we have encountered a walking error ( we have crossed a boundary ). We next check to see if we crossed it while holding an enemy in front of us. If so we press on and push him out, else we reverse or direction to move away from the boundary.

ifelse (eyeavg > detectlevel) [mwait 18 ; attacking, violate forward 20 right 360 stop!] [mwait 18 back 40 right 200 setwalkcount 0] ] ;going backwards if (walkcount < 0) [mwait 18 forward 30 setwalkcount 0] setwalkerror 0 repeat 32 [checksensors] ]

Now we check to see if we can see the enemy in front of us. If not we enter scanmode. This is where we start to spin around looking for the enemy. If we do see the enemy we then start to walk towards him/her.

;check distance ; ifelse (eyeavg > detectlevel) [ setscanmode 0 if (walkcount < 1) [setwalkcount (walkcount + 1)] ][ setscanmode 1 checkscan ]

Here we check to see if there is an imbalance in our eyes. This lets of know if our enemy is moving to the left or the right. The veerangle is a number from 1 to 10 that represents how hard we have to turn either left or right +10 or – 10.

The concept of veer was introduced to smooth out the robots walking. If every time we wanted to turn, we would come to a complete stop, and then turn, the robot's motion would be jerky. Therefore, the veer concepts makes one wheel turn faster or slower than the other. This allows us to veer a course without stoping.

Depending on how close we are to our enemy, determines how hard we veer. The closer we are the faster we need to turn (+10/-10), or we will lose him/her. If we are not that close, then we veer (+1/-1), so that we dont overshoot our correction.

If the imbalance in our eyes is less than 150 we disregard the change.

; check if we need to veer ; if (scanmode = 0) [ if (eyediff > 150) [ if (lefteye > righteye) [setveerangle -1] if (righteye > lefteye) [setveerangle 1] ] if (eyediff > 300) [ if (lefteye > righteye) [setveerangle -10] if (righteye > lefteye) [setveerangle 10] ] if (eyediff < 150) [ setveerangle 0 ] ] end

We are done with our thinking. The other functions are subroutines that help us peform the main functions. I will continue to add comments with time, until this code is commented from start to finish. In the meantime, please email me if you have any questions! Thank you.

-Edward

;******************************************************************************* ; SUB ROUTINES ;******************************************************************************* to abs :a if (:a = 0) [output 0] ifelse (:a > 0) [output :a] [output (:a * -1)] end to absdiff :a :b output (abs (:a - :b)) end to average :a :b output ( (:a + :b) / 2 ) end ; ; Reset all variables ; to resetvariables resett setframe_count 0 seteye_leftcounter 0 seteye_rightcounter 0 setsniff_leftcounter 0 setsniff_rightcounter 0 setsniff_middlecounter 0 setlefteye 0 setrighteye 0 setsniffleft 0 setsniffright 0 setsniffmiddle 0 setscanmode 0 setwalkerror 0 setwalkcount 0 setwalkholdoff timer setveerangle 0 setscan_lr 0 end ; Reset time after 5 seconds ; ; to checktimer ; If we are not walking reset timer ; if (walkcount = 0) [ if (timer > 5000) [ resett setframe_count 0 setwalkholdoff timer ] ] end ; Walk and check for boundary crossing ; ; to checkwalk if ((timer - walkholdoff) > 17) [ setwalkholdoff timer if (sniffleft > 950) [output 1] if (sniffright > 950) [output 1] if (walkcount > 0) [ fwd veerangle setwalkcount (walkcount - 1) ] if (walkcount < 0) [ bck veerangle setwalkcount (walkcount + 1) ] ] output 0 end ; Check Sensors ; to checksensors setsniff_leftcounter (sniff_leftcounter + (read-ad 7)) setsniff_rightcounter (sniff_rightcounter + (read-ad 5)) setsniff_middlecounter (sniff_middlecounter + (read-ad 6)) seteye_leftcounter (eye_leftcounter + (read-ad 3)) seteye_rightcounter (eye_rightcounter + (read-ad 2)) ; Check for 32 samples ; ifelse (frame_count < 31) [ setframe_count (frame_count + 1) ][ setsniffleft (leftshift sniff_leftcounter -5) setsniffright (leftshift sniff_rightcounter -5) setsniffmiddle (leftshift sniff_middlecounter -5) setlefteye (leftshift eye_leftcounter -5) setrighteye (leftshift eye_rightcounter -5) seteyeavg average lefteye righteye seteyediff absdiff lefteye righteye setframe_count 0 seteye_leftcounter 0 seteye_rightcounter 0 setsniff_leftcounter 0 setsniff_rightcounter 0 setsniff_middlecounter 0 ] end ; Scan for a target ; ; to checkscan ; scanmode = 1 ; if (scanmode = 1) [ ; has a frame passed be? if (frame_count = 1) [ ifelse (eyeavg < detectlevel) [ ifelse (scan_lr < 20 ) [ left 10 wait 2 setscan_lr (scan_lr + 1) ][ ifelse (scan_lr < 40) [ right 10 wait 2 setscan_lr (scan_lr + 1) ][ setscan_lr 0 ] ] ][ setscanmode 0 ] ] ] end

]]>

All

In this class we expanded on our last class where we dropped a baseball from the second story. In this class we timed the fall and calculated the height of the drop.

- We measured a 1 second drop that yielded a 5m height.
- In todays class we used Kinematics to calculate the velocity, that the ball would hit the floor.
- We then discussed that we could do the same for the escape velocity of the Earth, EXCEPT, that gravity changes as we move away from the earth.
- We then used calculus to calculate the total energy at infinity distance away from the Earth!
- We did this by visualizing that we could perform successive additions of slices where the gravity was changing by a factor of (r/s)
^{2}.

This concept of successive additions is the concept of Integration that we learned in the last couple of classes.

We then used Mathematica to perform the same Integration.

Here are the class notes:

-Edward

]]>

Today we tested our fight program, and we had a detailed review of the program.

Our winner was Maddy, the girl robot!

This program offers students a look into how an actual program would operate and control a robot.

We had functions that would read sensors and return a value. For instance the left-eye function would tell us how close something is to us on the left, and the right-eye function would do the same for the right.

We then would call simple functions that we created and reviewed in class. Like the average and absolute difference functions. These functions would return the average or difference between the left and right eye inputs. This would allow us to make decisions on what course of action to take.

Here is Maddy! The Winner of Fight Club! and her operator!

Here is the average function:

to average :a :b

output ( (:a + :b) / 2 )

end

This is how it is called to set the variable eyeavg:

seteyeavg average lefteye righteye

Here is the complete program fight.txt

I will be posting an entry where I dissect the program and explain it line by line.

Thank you,

Edward

Maddy in action!

]]>

Hi,

Today we learned about integration!

Integration is the concept of successive summation in order to calculate the area under a curve.

In class we solved this problem:

Compute the integral by computing the Riemann sums for a regular partition.

Using Mathematica we obtained the following:

, for each i

, for each i

Please note that for a very large n,

Now the easy way:

We then used Mathematica to get the same answer : …much easier :)

-Edward

]]>

Hi,

In this class we learned about inverse functions:

We reviewed what the log is nd how it is just an inverse function. We used it to calculate the number of years it would take our money to double.

]]>

Since I am now the father of 4 lovely robots (MARKIII) , that each take 4 AA batteries. I got tired of changing batteries. I wanted a way to charge the batteries without having to take them out of the robot. So I built a custom charger with a spare PIC18F2320.

Here is the most important piece of the design:

In this circuit, I have a PNP acting as an ideal current source. As long as the PNP s active the base current will determine the collector current regardless of the voltage at the collector. Of course the voltage at the collector needs to stay at least below 6V – 0.7V for the PNP to remain active.

The neat thing about this circuit is that you could supply any voltage to the emitter (same one that goes to the PIC) and you could charge any battery.

The idea is to use a GPIO to toggle the base current ON and OFF thus turning on and off charging. When no battery is present R4-collector will be at max voltage due to the GPIO being pulled high. As soon as the ADC voltage drops, you know that a battery was inserted and you can lower the GPIO to begin charging.

While charging you monitor delta V with the ADC and turn off charging at the appropriate moment. R3 will bias the LED current when charging, and let you know that you are charging. R2 is used to control the amount of base current and thus regulating the fixed collector current that is supplied to the battery.

Here is a picture of them nursing:

Here is a link to the code .

]]>

S.A.M – Software Automated Mouth.

I just got the robot to talk. :) **(trust me…it was not easy…)**

The robot is running on the Logochip and all of the code was done in Logo. I used a simple PWM of a resistor and a cap in order to produce and analog output:

The pic recreates the phonemes by creating a linear combination of two sine waves. This is done with a sine lookup table and some addition. It is a really tight loop since I could not spare a single MIP.

Here is the code : sampic.txt

Please note that I am running the Logochip on a PIC18F4620 with a 10Mhz resonator.

This gives me extra flash and sram space, plus increased processing power.

I will soon be giving the MARKIII robot a mouth….

-Edward

]]>

In class we created spiral program and reviewed all the concepts that we have learned.

We created a procedure called **box** and spiral. The box program call the spiral program and passes it to variables. The box program is called with one variable.

The new word that we learned **repcount **represents the count in the **repeat** loop.

Here is the program that we reviewed.

]]>

** **

**Another great class. Today we explored summation and limits. The students also derived two equations:**

** **

**Here is the first equation that the students derived (with a little help ;) )!**

**We used this equation to help derive the annuity equation. Here are some class notes:**

**Finally, here is an example with a $100,000 loan for 30 years at a yearly 8%.**

]]>