Tuesday, February 6, 2018

Falcon Heavy

Today is the scheduled launch date for the Falcon Heavy demonstration. As of this writing, the launch is on schedule for an 11:30 MST launch.

There is very little official guidance from SpaceX as to what to expect. Elon Musk has stated that minimum mission success is clearing pad 39A far enough such that any further failure doesn't destroy that pad. There has never been a catastrophic failure at pad 39A, and Musk would like to keep it that way.

However, the plan is to do a boost, then three burns of the upper stage. The first finishes launch to LEO. The second is about 30 seconds, and seems to put the booster into a GTO-like orbit. Lifting a heavier spacecraft into full GTO takes about a minute, so there is some hint that this will go into an elliptical orbit that is short of GTO. Part of the demonstration is a 6-hour coast. They are doing it on this flight because the upper stage is very similar to any normal Falcon 9 upper stage, and any demonstration on this stage would apply there. This coast is what would be needed for a 3-burn GSO direct insertion, that apparently is very interesting to the military. For one thing, it would demonstrate that the upper stage could put a GPS satellite directly into its target orbit, like the much more expensive Delta IV medium. A bit more oomph and a similar endurance would put a spacecraft directly into GSO.

In any case, the consensus on NasaSpaceflight is that the target high orbit is one with a period of around 6 hours. After this coast, the second stage would be back at perigee, ready to take maximum advantage of the Oberth effect.

SpaceX has claimed that they will put the payload (A cherry-red Tesla Roadster) into an "earth-mars heliocentric orbit". The launch window for Mars is in May, so they will be launching 3 months out of the window, but since this is such a light payload, they should have plenty of C3 and probably could target Mars if they wanted. However, I think that they will instead target an orbit with periapse at Earth and a C3 typical of launching to Mars. The payload will reach the vicinity of Mars orbit, but Mars will be far far away by then. In fact, to be responsible about Planetary Protection, they should launch into an orbit which will not actually intersect Mars orbit at all, so that there is never any possibility of the car impacting Mars.

Running the numbers based on the Trajectory Planner 1.1.1 from Orbit Hangar, I get a departure C3 of 23.9 km^2/s^2, with a departure today and an arrival on October 17, 2018. The flight time is 252 days. This C3 is high for a Mars launch, but should be doable with such a light payload.

If they are targeting Mars, then the launch vehicle must be able to adjust azimuth in order to target Mars at any time during the window. If they are just going for a given C3, they can use the same azimuth whenever they go. Since ASDS is parked somewhere definite to catch the core stage, I estimate that they are targeting a fixed azimuth independent of launch time.

There are no signs of high-gain antennas or solar panels on the payload, so it is almost certain that once the battery runs down, the payload will become inert. However, the payload is an electric car, with many many amp-hours of battery life. The car radio might run for hours or days.

Monday, August 21, 2017

Live, from the eclipse path

The Kid Attractor - works on adults too.

Cookie Monster
I'm in Rexburg, ID where the crowds are not as bad as I feared. I left Logan, UT this morning at 4:00am. Traffic on I-15 was interesting. It never slowed down below the speed limit, but there were easily 20 times as many cars heading north as opposed to south. We arrived at Rexburg at 7:30 and found plenty of parking in a church parking lot just south of the Temple.

Just after first contact
Things of note:


  • It did get noticeably darker as the eclipse passed 50%
  • We could see the shadow approach from the west. It was hazy that direction, and I could see a band of dark start at the horizon. It looked like it was getting vertically wider rather than closer.
  • Totality itself cannot be done justice in pictures. I took pictures but used my eyes too. Light level was close to that of just after sunset.  The sky was a deep blue purple. We saw the diamond ring, which was MUCH brighter than the rest of the corona. The corona is white, and rather narrow with 3 long streamers  (more than one solar diameter) One at 12:00, one at 1:30 and one at 7:00. The disk of the moon was the same color as the sky.
  • I thought I got crowd shots, and everyone around said that it was totally worth it. Unfortunately for some reason either the video was never captured or was deleted :(
  • No one bothered to stay long after totality - we just all packed up and ignored the reverse of the spectacle we had just seen.


See you all in 2024!

Saturday, July 22, 2017

Today's Episode of "It's my responsibility, but..."

"...The datasheet diagrams didn't have the pins labeled."

This time, it is the encoder board.


Here, it isn't obvious which pad in the footprint goes with which pad on the part.

It doesn't matter anyway, because a closer examination of the footprint and the Digikey list of optical sensors reveals that I bought the wrong part. The footprint on the board is marked QRE1113, but it is actually for an Omron EE-SY193. D'oh!


Well, back to the fab again, for both boards. I'll use the QRE1113 parts that I have to test if the parts even fit in the hole. If not, I'll have to use the EE-SY193.

All parts of this project are my responsibility. It can't be otherwise, since there isn't anyone I report to or who reports to me. My partner is a special case.

Friday, July 21, 2017

Dagnabbit!

That beautiful purple board I received yesterday won't work. If it had been stuffed and plugged in, it would have immediately shorted out anything plugged into it.

One of the features on the board is a super-wide (for a 6-mil PCB) strap between the two adjacent 5V pins coming from the Pi. When I had a close look at it, I saw a thin little gold crescent around part of the hole. It took a little bit for it to dawn on me that this was the ground plane, which was visible through the mask, plated in gold, and not protected from shorting with the other contacts:
 The effect is everywhere on the board. I saw it first on the strap in the upper-left, but this magnified version shows it on the motor power section and connection to the Arduino. Note the crescents around the top of D3~ and RST, and the slivers of ground plane visible through the mask around the isolator footprint.

I don't think that there is anything that can be done to fix it. I also don't think that the encoder board is affected, so at least I can still use that. I'll try to stuff it, but I will check continuity closely. If any of the solder bridges the 6mil gap, then the short will exist.

I'm pretty sure the problem comes from settings in the ground plane. Since OSHPark can make 6mil boards, I take full advantage of the feature. Unfortunately, this interacts with a bad default in Kicad. Fortunately, that is easy to change, but it would have been nice to know fifteen dollars and two week ago. The money isn't a big deal, it's the time.

Kicad was even trying to tell me that something bad was about to happen. Not from the DRC (although that would have been nice) but in the images. Here is the old, bad design:

The purple rings around the pads are the soldermask gap. You can see a slight red tinge around the edge where the mask gap overlaps the ground plane.
The OpenGL preview shows it too, perhaps in an easier-to-understand form.

To fix it, use the Dimensions/Pads Mask Clearance menu option

Change the Solder mask clearance value from its default... (Yes, I design my boards in US units. You got a problem with that?)

Change it to zero.

The borders of all the pads are now black, indicating the solder mask gap doesn't span the space between the pad and the ground plane




 This option has settings in several places: The global setting I talk about above, the zone setting (which I haven't found), the footprint setting, and the individual pad setting. The later settings in the list have priority over the earlier ones, but the earlier ones are used as defaults.

In general with modern fab processes, you should set this value to zero. This will describe a hole in the solder mask the exact size of the pad. The fab can and will edit this to match their process, so don't worry about getting it too small.

Thanks to a YouTube video by My 2uF for help finding this setting.



Thursday, July 20, 2017

Yukari 5 parts!

Front side of each board
Look how awesome the gold logos look!
Here is the Pi wearing it's hat (upside down, because the logos are so cool)
And the hat wearing it's accessories




Thursday, August 25, 2016

Radiation-pressure propulsion for nano-spacecraft

Abstract: The Breakthrough Starshot project proposes using radiation-pressure propulsion to send multiple spacecraft in the gram-range mass to interstellar targets. There are numerous engineering challenges to accomplishing this mission, but their project discusses speeds and accelerations previously only discussed for cannon projectiles and particle physics experiments. This article examines the problem from first principles to see if the project is even orders-of-magnitude possible. A preliminary check on their numbers seems to confirm that the project is possible in principle.
 Radiation pressure has been hypothesized since the early days of special relativity and quantum mechanics. It is a simple consequence of the mass-energy equivalence and the photon nature of light. Quantum mechanics states that light is made of photons, and that each photon is a discrete bundle of energy. The energy \(E_{pho}\) carried by each photon is proportional to its frequency \(\nu=c/\lambda\), and the proportionality constant is Planck's constant \(h\).

\[E_{pho}=h\nu=\frac{hc}{\lambda}\]

Everyone knows the famous mass-energy equivalence equation \(E=mc^2\). However, that is only a special case of the momentum equation:

\[E=\sqrt{p^2c^2+m_0^2c^4}\]

We can solve this for the momentum of a photon, considering that its rest mass is zero.

\[\begin{eqnarray}E_{pho} & = & \sqrt{p_{pho}^2c^2+0^2c^4}\\
& = & \sqrt{p_{pho}^2c^2} \\
& = & pc\\
\frac{hc}{\lambda}&=&p_{pho}c\\
\frac{h}{\lambda}&=&p_{pho}\end{eqnarray}\]

Note that momentum is a vector quantity, but this just deals with the magnitude. The direction of the momentum vector is the direction the photon is traveling.

Now, we know the energy and momentum of each photon, so we know that if we throw so many joules of photons at a target, it will transfer so much momentum. The irradiance is defined as the power \(P\) (energy \(E\) per unit time \(t\)) of the light hitting each unit area of the target, so the units are W/m^2 or J s^-1 m^-2. We can calculate it from the amount of energy striking the target of known area \(A\) per unit time:

\[I=\frac{P}{A}=\frac{E}{tA}\]

So given a certain amount of irradiance with a known photon wavelength, how much momentum does that light carry? First, figure out how many photons per time per area \(I_{pho}\) that irradiance represents:

\[\begin{eqnarray}I_{pho}&=&\frac{I}{E_{pho}}\\
&=& \frac{I\lambda}{hc}\end{eqnarray}\]

The dimension of photon irradiance is photons per time unit per area unit (photon s^-1 m^-2 in SI units).

Now a bit about momentum. Again, everyone knows Newton's second law \(\vec{F}=m\vec{a}\), but again this is a special case. Force is defined as the change in momentum per unit time:

\[\vec{F}=\frac{d\vec{p}}{dt}\]

For massive objects at sub-relativistic speeds, momentum is defined as the mass of the object times the velocity of the object. For relativistic conditions, we use the energy relation above, where energy still has the customary units J=kg m^2 s^-2. Working through the units of the energy equation in the special case of a photon, we find that momentum still has the same units as it does in sub-relativistic conditions.

So from this, a given amount of energy of photons carries a certain amount of momentum. A certain power of photons carries a flow of momentum per unit time, or in other words Force. A certain amount of momentum flow impinging on a certain area is the same as a force exerted on that area, or a Pressure \(\rho\). So, we can calculate the pressure exerted by a given irradiance of light from the intensity in photons/time/area, multiplied by the momentum of each photon, which gives momentum/time/area which equals force/area which equals pressure:

\[\begin{eqnarray}\rho&=&I_{pho}p_{pho}\\
&=&\left(\frac{I\lambda}{hc}\right)\left(\frac{h}{\lambda}\right)\\
&=&\frac{I}{c}
\end{eqnarray}\]

So the pressure exerted by the light is the irradiance of the light divided by the speed of light. That is amazingly simple, and notice that both Planck's constant and the wavelength cancel out. Now we can start plugging numbers.

First, let's do one of Clarke's space yachts. It weighs on the order of 1000kg and has on the order of 1km^2=1,000,000m^2 of sail, and it uses natural sunlight. How much force does it collect and what is its acceleration? Note that since the sails are reflective, the light is reversed in direction and has a momentum change of twice its original momentum, so we collect twice as much force as the momentum suggests.

\[\begin{eqnarray}I& & &\approx&1400\mbox{W/m}^2\\
c& & &=&299,792,458\mbox{m/s}\approx 3\times 10^8 \mbox{m/s}\\
\rho&=&2\frac{I}{c}&=&2\frac{1400}{3\times 10^8}=9.4\mu \mbox{N/m}^2\\
A& & &=&1,000,000 \mbox{m}^2\\
F&=&P_{pho}A&=&9.4\mbox{N}\\
m& & &=&1000 \mbox{kg}\\
a&=&\frac{F}{m}&=&\frac{9.4}{1000}=9.4\mbox{mm/s}^2\approx1.0\mbox{mg}
\end{eqnarray}\]

So the whole sail exerts a measly couple of newtons. Pulling on a ton of mass, we get almost a full milli-g of acceleration. Not a whole lot, but in order of magnitude of that described in the story.

Now we get into the big numbers. The game Adventure Capitalist teaches us to not be afraid of big numbers, so lets go get some. The Starshot project describes using gigawatts of power on spacecraft weighing grams. Among the enormous engineering challenges are:

  • Focusing gigawatts of power onto square-meters sized targets over distances of billions of meters
  • Having a reflective enough sail that the GW/m^2 incident power doesn't vaporize the sail
  • Having a tough enough sail that the MW/m^2 absorbed power doesn't vaporize the sail
  • Having a thin enough sail to stay within the mass budget
  • Building a spacecraft with a useful payload, power source, and communications system that will work over interstellar distances and stay within the mass budget
  • By the way, the mass budget is about 10g total.

Putting all of these aside, they discuss a spacecraft with a mass of about 10g, a sail area of about 16m^2, and multiple gigawatts of power focused on it. Let's go with 1GW/m^2, or 16GW total, to see what we get:

\[\begin{eqnarray}I& & &\approx&1\mbox{GW/m}^2\\
P_{pho}&=&2\frac{I}{c}&=&2\frac{1\times 10^9}{3\times 10^8}=6.66 \mbox{N/m}^2\\
A& & &=&16 \mbox{m}^2\\
F&=&P_{pho}A&=&16\times 6.66=106\mbox{N}\\
m& & &=&0.01 \mbox{kg}\\
a&=&\frac{F}{m}&=&\frac{106}{0.01}=10.6\mbox{km/s}^2\approx1080\mbox{g}
\end{eqnarray}\]

Well, that's some git-up-and-go, alright. How long does it take this to get to a target speed of a good chunk of the speed of light, say 60,000km/s (0.2\(c\))?

\[v=at\]
\[\begin{eqnarray}t&=&\frac{v}{a} \\
 &=&\frac{60,000,000}{10600}&=&5660 \mbox{s}
\end{eqnarray}\]


That's not too bad, a little over 1.5 hours, and real close to 1 LEO period, but not what the paper is discussing, which is on the order of 10 minutes. What acceleration is needed for that?

\[v=at\]
\[\begin{eqnarray}a&=&\frac{v}{t} \\
 &=&\frac{60,000,000}{600}&=&100 \mbox{km/s}^2\\
F&=&ma&=&0.01(100,000)=1000\mbox{N}\\
P&=&\frac{F}{A}&=&\frac{1000}{16}=62.5\mbox{N/m}^2\\
I&=&Pc&=62.5(300,000,000)=18.75\mbox{GW}
\end{eqnarray}\]

This is about 10000g. Now we are talking cannon-type acceleration. Since the acceleration is about 10 times greater, it will require 10 times the power, or a couple hundred gigawatts. This is a good fraction of the electricity usage of the United States, so it is a large but doable amount of power. We only need it for 10 minutes. The paper discusses putting the laser in space, which would require a gigawatt-scale power source in space. I suppose a couple of square kilometers of solar cells could do that.

If all of the engineering problems are solved, this could work. There isn't anything physically impossible about it. The engineering challenges are large, but the Starshot project claims that each can be solved incrementally. We don't have to shoot at stars first -- imagine getting back to Neptune in a couple of days, and then being able to orbit once you got there?

References

Saturday, August 6, 2016

August 20 progress passed!

Yesterday Yukari 4 passed the August 20 progress verification point. A whole 15 days early, too. Here is video proof:


Thursday, July 28, 2016

St Kwan's Is Expanding

We would like to welcome Kirktopode to the St Kwan's Family! He has the goal to enter the embedded electronics field, and I have the goal of completing the robot without going crazy. We are perfect for each other!

Also, all of the robot code and design stuff is now on Github. Kirktopode is holding the master version, and I have a fork of it. I am using another one of my projects to hold the wiki in which I am documenting things in English.

Sunday, July 24, 2016

Robodometer

Last year I tried to implement a wheel encoder in between heats and failed. The ambient light was just too bright. So this time I am building the wheel encoder into the gearbox. I took the spare gearbox apart to see what the best way to do it is. Inside the casing is a differential gear in the form of a cylinder with gear teeth around the outside and the differential gears inside. The cylinder is sealed, held together with 4 screws. But, the outside of the cylinder is perfect for my design. The gearbox cover plate in that part of the gearbox is relatively easy to remove, and in just the right spot. If a hole is drilled through that plateau optical sensor can be set up to look through the hole and read the half of the differential cylinder face which is painted white. Two such sensors can be used to mak single-track quadrature encoder, which can tell whether the wheel is turning forward or reverse.

I have a pair of QRF1114 sensors specifically designed and obtained for this purpose. This part is basically just an infrared LED and an infrared phototransistor in the same case. It isn't directly useful as-is, but I combined it with a few resistors and made a three-terminal analog device.





Friday, May 13, 2016

Hooray for distributed backups!

BACK UP ALL THE THINGS!
I found a backup of my database from April 21 of this year, which was only a couple of days before the failure. That should have all of my wikis and gallery data, and therefore represents the second-most important data I have. The most important is the code, and that is backed up by means of git. I know for sure that there is a valid git repository on one of my portable USB disks



Thursday, May 5, 2016

Yet Another Episode in the Annals of Data Stewardship

Having learned my lesson from before, I did not set up my filesystem as one big raid0. I did a btrfs raid5 instead. When one of the disks finally did give out, it wasn't with the click of death I heard before, but with read errors. The btrfs degraded, and by mounting read-only in recovery mode, I was able to use the two good disks in order to get my data.

Or so I thought.

A word on the issue I was having. I was seeing "stale file handle" warnings, of the type you see when you are in a folder that is NFS mounted, after you lose connection. But, this wasn't an NFS system. I rebooted the system and it wouldn't come up, because the btrfs refused to mount. After manually mounting in degraded mode, many of the disk accesses reported errors in dmesg, about the generation of certain metadata being off of the expected value, often by hundreds or thousands of generations.

First, I decided that I had lost confidence in btrfs -- if it wasn't going to keep working in the presence of a disk failure, what was the point? I spent the next several days scraping data off of the btrfs and putting it wherever I could find a place for it - on the USB disks I have, on other computers, on the system disk, etc. I then replaced the bad disk and formatted them all as zfs - now possible since Ubuntu 16.04 includes a native zfs driver.

Finally, I started copying data back onto the zfs. All appeared to go well, until I tried to bring up the wiki. The LocalSettings.php file was completely blank - it had the expected value, but all bytes in the file were 0x01 . Hrm.

Turns out a lot of files were like this. Files I care about, like the database, the git repositories, etc. It seems like the newer the file is, the more likely it is to be damaged like this.

No problem, I've got backups. A raid5 is not a backup, so I had the most important data copied off onto several other systems.

Or so I thought.

My backup script runs on a cron every night, and had backed up the bad data and spread it all around over the good data.

Oops.

It isn't a total loss. I have all my code in a git repository on the big USB disk. I have an old backup (from December, I think) of all the data I considered important. I did lose a lot of video :( but I don't think I lost anything from Florida 5.

So I think.

Monday, April 4, 2016

Hearing but not Understanding

I just heard a conversation drift over the walls of my cube. I could identify the speakers, I could recognize their voices, but I couldn't understand it. It was as if I couldn't parse spoken English. What was actually happening was that, in between the noise level of the fan in my cube, the sound insulation in the cube partitions, and the low level of the conversation to begin with, I just couldn't make it out.

But then how was it that I was able to identify the voices and put names to them, when I couldn't parse them? It means that at some level, identifying voices is easier and more noise-resistant than picking words out.

Or it means that the spoken English section of my brain is broken. I have neither spoken nor heard anyone speak since then, a few minutes ago.

Thursday, March 31, 2016

Check PCLK measurement

Check if the user code measures PCLK properly. If it doesn't, then the baud rate calculation will be wrong. Since one of the symptoms that has been seen is that the RX light on the FT232 doodad flickers, but no characters appear in putty, it is possible that the baud rate isn't what we think it is.

Consider also calculating the baud rate registers and stuffing them manually. If this works, then it's the PCLK stuff that is broken.

Friday, March 11, 2016

The Secret to Success

  1. Pick something you like doing.
  2. Do it and do it and do it until you don't like doing it any more. This will always happen at some point.
  3. Keep doing it.
Following these steps don't guarantee success, but failing to follow them guarantees failure.

Tuesday, February 16, 2016

Cortex M4 FPU

For a while I was having trouble getting my part to print any FPU calculations. Finally it occurred to me that maybe the FPU has to be turned on, and that the ISP wasn't doing it since it didn't use it.

It turns out that you DO need to turn on the FPU:

4.6.6 Enabling the FPU
The FPU is disabled from reset. You must enable it before you can use any floating-point instructions. Example 4-1shows an example code sequence for enabling the FPU in both privileged and user modes. The processor must be in privileged mode to read from and write to the CPACR.
Example 4-1 Enabling the FPU
; CPACR is located at address 0xE000ED88
LDR.W R0, =0xE000ED88
; Read CPACR
LDR R1, [R0]
; Set bits 20-23 to enable CP10 and CP11 coprocessors
ORR R1, R1, #(0xF << 20)
; Write back the modified value to the CPACR
STR R1, [R0]; wait for store to complete
DSB
;reset pipeline now the FPU is enabled
ISB

In effect, the FPU is counted as coprocessor 10 and 11. Cortex-M doesn't fully support the concept of coprocessors, but it does in this context. We allow full unpriveleged access to coprocessors 10 and 11.

I don't know about waiting for the store to complete and resetting the pipeline. I just put some C++ code to do this long before the FPU is used, and let a bunch of other work instructions flush the pipeline.

Friday, February 12, 2016

Getting on board the LPC4078

A few things make the LPC4078 dramatically different from the LPC2148 that I am used to:

  1. This is a Cortex-M4, with a much different interrupt and reset vector table. Instead of a set of ldr pc,[pc,#24] instructions followed by addresses 24 bytes later, we have just a table of addresses. The first one is the value to put into the stack pointer upon reset (so there is no required stack setup code) and the second one is the value to put in PC on reset. Subsequent values include exception and interrupt handler addresses.
  2. As with the 2148, there is a bootstrap program. On reset, the bootstrap vector table is mapped to 0x00000000, rather than the more obvious solution of having the reset value of the vector table address register point at the bootstrap.
One of the ugly things about my old LPC2148 is that much of it was Not Invented Here. Since this is a hobby project, I can use as much of my time to do whatever I feel like, including reinvent wheels! So, I get to figure out how to start up a Cortex-M4 from scratch.

I'm not there yet.

I haven't gotten my code to run directly yet, so there is still a problem with my vector table. But, I can get my code to run with the help of the ISP, after some experimentation.

The ISP maps a total of 512 (0x200) bytes of memory as its vector table. This is room for 128 vectors, while the actual number of vectors it uses is only 7. I can tell because the reset vector points at what would be in slot 7. In any case, this code is mapped to address 0 at startup. When I was using the ISP to launch my code, I originally had only exactly enough memory reserved to hold my table, and my code started immediately after, at address 0xE4 as it happened. Well, that code was covered up by the bootstrap. After rearranging my program so that a full 512 bytes was allocated for the table, things worked much better.

Also, the ISP uses an autobaud feature when it sets up the serial port. You send a question mark, and it times the bits on that to set up thebaud rate registers. However, the ISP uses a feature I don't, and that is the fractional baud rate register. This is able to tune the baud rate at a relatively fine grain to between 1x and 2x the rate called for by the coarse baud rate registers. When the ISP is used to kick off my code, my code sets the coarse baud rate, but didn't touch the fractional baud rate register, which was left at about 1.5 . Therefore the part was programmed to talk at the wrong rate by 50%, out of tolerance for the serial port. The FT232 could tell that the part was talking, but couldn't understand any of it.

With those two things taken care of, I can now start my code with the ISP, from the very beginning of my code. Next step is to see what I am doing wrong such that my code doesn't start itself.

Tuesday, February 9, 2016

LPC4078 operational

I am continuing my project of doing robot stuff with a buddget of zero, plus the stuff on my bench. Well, the stuff on my bench includes a Loginator2368 purple board, and a box of LPC4078 Cortex-M4 microcontrollers. Those controllers happen to be pin-compatible with the LPC2368 the board was designed for. In this case that means that all the power pins have the same jobs and voltage levels (even if they have different names and perhaps different internal connections), all the special pins like reset are in the same place, and all the GPIO pins have the same numbers, and where the 2368 and 4078 have the same peripherals, they have compatible pin assignments.

One thing that the 4078 has that the 2148 doesn't is internal pullup resistors. I can take advantage of these to reduce the part count in several places.

Therefore I got out my soldering iron and finally attached the board and LPC4078. I was trying to figure out what was the minimum amount of components I could get away with, since I can't find my solder paste stencil for this board, and would have to manually solder everything. I decided to skip the power section, so no external battery or regulator. I skipped the USB section, the LEDs, and the voltage reference. I also skipped the crystal, since the part has an internal RC oscillator which is good enough for now. I even skipped all of the bypass caps.

The only part that it looked like I absolutely needed was the reset button, since my first read on the datasheet didn't show the reset pin as having a pullup. It turns out that it does, so, I didn't even need that. I did end up stealing a push button from another board and using it as a reset switch.

I did the normal SMD IC soldering thing. I carefully lined up the part on the board, then used a normal soldering iron and normal solder to glob all the pins on each side down, and to each other. I then used wick to clean up all the bridges. This naturally leaves the connections to the board intact. I then soldered on the reset button, more as a convenience than anything. (Next time, leave a reset terminal on the edge!) Also solder a shield 6-pin top-and-bottom connector onto the power and serial connections.

Then, hook it up to power. No smoke, the chip isn't hot, it passes the smoke test. But, I've seen this board not work before, with the LPC2368 that it was designed for. So, the real test is running the ISP.

?
Synchronized
Synchronized
OK
12000
OK 

It works!!! I had to guess at the frequency it wants, since I don't have an oscillator attached at all. The internal RC oscillator runs at 12MHz, so I put that in.

Now to massively restructure the code. A Cortex-M4 is quite a different beast than an ARM7TDMI. It has an FPU and built-in VIC instead of the VIC as a peripheral. It also doesn't use 32-bit ARM instructions, but (mostly) 16-bit Thumb2 instructions. The 4078 is also a much different part than the 2148, with a different set of registers in different places. But, probably 90% of the code can be in common, if we carefully separate the code into the part which is different and the part which is common. That's the next big adventure. Throw one switch in the Makefile and compile for a 4078 instead of 2148.

Friday, January 8, 2016

Practical CRTP (or lack thereof)

I have recently performed an experiment where I took the Loginator code and removed all dynamic polymorphism in place of static polymorphism. The motivation was the fact that since the sensors were all hard-wired to the board, all references to them could be figured at compile-time, and static polymorphism plus the optimizer and inliner could make "better" code. I also had an irrational fear of the vtables being corrupted.

Having gone through this exercise, I think I can say that CRTP is not the right way to do static polymorphism. It works, but it is ugly and infectious. If a class uses an object which is defined with CRTP, that class itself must also be made to use CRTP. I don't know if the machine code produced is faster, but I do know that it is significantly larger.

The motivation for changing back is the hardware description block which I am adding to the Loginator code, in hopes of being able to unify the Logomatic, Loginator, Rocketometer, Rollercoasterometer, and Pocketometer. My idea is to be able to load the same binary image into any LPC2148 based hardware I have or make, and have the software read the hardware description block to see what hardware it is attached to. This is all done at runtime, so we need dynamic polymorphism again.

CRTP isn't all bad. It works fine for instance in the dump class, where you can use it to make specializations of dump which are resolved at compile time. The problem arises when you want to pass a CRTP object as a parameter. At that point, the reference or pointer to the object has to be CRTP also, which frequently causes the whole class to need to be CRTP.

The idea then is that the general-purpose drivers are built into the code, and constructed at runtime from the hardware description block.

Tuesday, August 18, 2015

Magnum Torch

A magnum torch is an Extra Utilities block which prevents the spawning of hostile mobs within a certain space around it. How? Like this:

 public static boolean isInRangeOfTorch(Entity entity)
  {
    for (int[] coord : magnumTorchRegistry) {
      if ((coord[0] == entity.field_70170_p.field_73011_w.field_76574_g) &&
        (entity.field_70170_p.func_72899_e(coord[1], coord[2], coord[3])) && ((entity.field_70170_p.func_147438_o(coord[1], coord[2], coord[3]) instanceof IAntiMobTorch)))
      {
        TileEntity tile = entity.field_70170_p.func_147438_o(coord[1], coord[2], coord[3]);
        double dx = tile.field_145851_c + 0.5F - entity.field_70165_t;
        double dy = tile.field_145848_d + 0.5F - entity.field_70163_u;
        double dz = tile.field_145849_e + 0.5F - entity.field_70161_v;
        if ((dx * dx + dz * dz) / ((IAntiMobTorch)tile).getHorizontalTorchRangeSquared() + dy * dy / ((IAntiMobTorch)tile).getVerticalTorchRangeSquared() <= 1.0D) {
          return true;
        }
      }
    }
    return false;
  }


This is a method which supports both the chandelier and magnum torch. Each of those has the getHorizontalTorchRangeSquared and getVerticalTorchRangeSquared methods. It doesn't matter how this method gets called, or what the obfuscated functions are. The important bit is that line which works with dx, dy, and dz. Those are obviously the distance from the torch to the entity in question (the mob trying to spawn). The formula looks like this:

\[\frac{\Delta x ^2+\Delta z^2}{h^2}+\frac{\Delta y^2}{v^2} \le 1 \]

Rearranging slightly, we see the formula for the surface and interior of an ellipsoid:


\[\frac{\Delta x ^2}{h^2}+\frac{\Delta z^2}{h^2}+\frac{\Delta y^2}{v^2} \le 1 \]

The semi-axes in the horizontal direction are both \(h\), while the semi-axis in the vertical direction is \(v\). Looking at the implementation of these blocks we see:

public float getHorizontalTorchRangeSquared()
  {
    if ((func_145838_q() instanceof BlockMagnumTorch)) {
      return 16384.0F;
    }
    if ((func_145838_q() instanceof BlockChandelier)) {
      return 256.0F;
    }
    return -1.0F;
  }
 
  public float getVerticalTorchRangeSquared()
  {
    if ((func_145838_q() instanceof BlockMagnumTorch)) {
      return 1024.0F;
    }
    if ((func_145838_q() instanceof BlockChandelier)) {
      return 256.0F;
    }
    return -1.0F;
  }
 


So, the magnum torch clears a spheroid around itself with an equatorial radius of 128 meters and a polar radius of 32 meters. Similarly the chandelier clears a sphere around itself of radius 16 meters.