Sunflower Array

I’ve made the PCB for with the 74AC240 based on this design from http://www.smfr.org/robots/robot_images/dualsolarhead_schematic.png :

Hoping that it works better than the 540 version with the solar midpoint.

IT DOES! It is far more responsive and efficient and works with the solar panel! It has a funny quirk where it will first turn the wrong way then correct itself in one direction though…Next i’ll make it on a super small extra compact board and try the other circuit option:

It’s much more compact that the previous version. The photodiodes could be removed to make it even smaller. It took me around 25 minutes to assemble at a comfotable speed. By far the least efficient element of the assembly is the braided wire which is causing mini shorts :

There is already some interesting interplay with the two machines side by side…

3D model of fancy motor version:

Here’s a version with a tiny gear motor. The motor appears to lock up at low currents however so it doesn’t work super well. It’s also very difficult to attach the motor axle to the bottom platform. 

With the metal gearmotor it works much better:

And this version with the panels lower down:

Here is a tall version:

Here’s a compact design with a “flipper” arm:

The idea of pulling the solar panels from the board, exposing the electronics and creating the tilt naturally.

The little metal cap is actually a nice part of the look of the machine:

I have made the board thinner so that it fits perfectly over the gear motor:

Here’s a shot of it looking pretty:

Llama edition (it’s a heat sink). This photo makes me think I could have fun with shadows like in the 1970 Il Conformista film:

I see a monocled mustachioed Monopoly man here somehow:

This idea distributes the things to look at around the machine (one side has solar panels and the gear motor, the other has electronics and the underside gold lettering on the solar panels). When the machine is facing the sun we get to see the electronics. I guess the electronics is also sheltered from the heat of the sun a bit?:

Here are some feet ideas for the resin printer using small set screws and (in the right model) Pogo pins:

Here are two versions of the tripod design. One has the electronics as a backpack and hides it from the sun, the robot has two faces. The other has the “face” of the robot face the sun, in one photograph the whole robot is visible.

Version 1:

Version 2:

****

Side to side comparisons:

 Another idea for pogo pin feet using the crowned tips:

 

***

I made the barebones circuit in extra slim also:

debugging the previous version, it appears that the solar panels are indeed producing the expected voltage and current (2 x 1.67V, 18.4 mA), the voltage trigger and mosfet are working, the capacitor is charging, and the voltage to the motors is spiking. However the motors aren’t so much turning as twitching. The motors appear to be identical to others that are working however. Changing the capacitor from .22F to .15F changed nothing. 

EDIT:

I had another stab at this:

I noticed that the charging and triggering part of the circuit appeared to be working but that the motor was not firing. I assumed then that there was a soldering problem on the 74AC240 pins somewhere. I tested a copy of the same boards from the same batch to see if there were any problems with the etching itself, they all seemed good with no shorts and clean traces. I tested a blank 74AC240 as well and found that the only pins that were internally connected were 9 (Y1) and 10 (GND) – though I’m not sure why this is the case. I took a voltmeter to measure if there were any shorts between the pins on the IC and found that everything was mostly normal. Looking under the microscope it occured to me that the problem might be that the pins of the IC aren’t fully touching the pads below as they appeared to have been soldered quickly. In order to assume myself that everything was indeed well connected I reheated each of the pin connections and retested that I didn’t introduce any shorts. I then switched out the larger motor for a more efficient smaller DC motor. Testing with artificial light I now have normally functionality!

The second malfunctioning solar head has a different issue: It charges up fine from having no power and spins the motor no problem. But after a few times it stops triggering at hovers around 3.6V…I resoldered the connections and had the same issue. The voltage trigger appears to be triggering despite the voltage staying high. In the end I switched the bigger metal gearmotor for a small vibe motor and it worked just fine. I think I can conclude from this that the circuit I used is not suitable for the metal gear motors but works fine with smaller ones.

I am now looking into making this circuit even smaller using TSSOP-20 packages of the 74AC240 and maybe 0603 smd components too. I plan to make this double sided and to have the boards made at PCB way after testing a prototype circuit in the lab.

 

The circuit works fine after I had to resolder some of the IC pins to the pads (they seem to hover just above sometimes despite the soldering) and fixing a short between the two sides of the MOSFET by lifting up the positive side of the SMD cap up.

 

Testing with a single 3.4V panel and…it turns! I’m going to try to add the light detection now.

And this is how it could be integrated into the 2DOF design: 

This is a second option which would involve probably halving the above circuit and making it double sided. 

 

 

Another idea is to see how far this minimalism and miniturization can go, for instance with a single solar panel capable of charging up the cap to 3.3V ish. It could be 1DOF or 2DOF. Testing with the power supply with 4,46V @ 5,9mA it works no problem with the small gear motor. We’ll see if that’s the case with the actual solar cell soon.

Monocrystalline Solar Cell 24.5mW (4,46V Current – Short Circuit (Isc) 5,9mA)

https://www.digikey.fr/product-detail/en/anysolar-ltd/KXOB25-01X8F-TR/KXOB25-01X8F-DKR-ND/10127250

KXOB25-01X8F-TR ANYSOLAR Ltd | KXOB25-01X8F-DKR-ND DigiKey Electronics

Monocrystalline Solar Cell 26.3mW 5.53V:

https://www.digikey.fr/product-detail/en/anysolar-ltd/KXOB25-02X8F-TR/KXOB25-02X8FDKR-ND/9990483

KXOB25-02X8F-TR ANYSOLAR Ltd | KXOB25-02X8FDKR-ND DigiKey Electronics

Here is what it could look like 1DOF:

…and 2DOF:

If the solar panels are a bit offset from the boards then the light sensors could be directly on the board and not need to be offset themselves from the board. 

****

I actually have one of these lying around to test the one panel idea (3,4V
@ 4,4mA): 

https://www.digikey.fr/product-detail/fr/ixys/KXOB22-01X8/KXOB22-01X8-ND/2754274

Here it is working! (remember that the “GND” side of the photo bridge actually connects to the ENABLE of the 74HC240)

some other panel configurations:

I could have the light sensors on either end. 

A little higher up…

Satellite inspired:

Here’s a quick 3D print:

Not even sure if adding another DOF will have a big effect, over the course of a day how much will it actually tilt up or down?…

Dual Solar Tracking Part III

Another idea is to start with the actual solution (two small servos) and make it look better. It’s sturdy and already balanced. It just needs a hinge and a tilting arm:

With a makeshift hinge and tilt arm:

This would only require an Arduino mini pro and some super caps charged by a solar panel through a diode.

Some other more simple options:

For a miniature 2DOF.

A mini 1 DOF.

  The 2 metal gear motor design I was working with early on.

*****

Here is a super simple two servo motor controller that recharges supercaps through a diode:

This works with the code below as a test:

#include <Servo.h>

Servo myservo1; // create servo object to control a servo

Servo myservo2; // create servo object to control a servo

int pos = 0; // variable to store the servo position
int threshold = 100;

void setup()
{
myservo1.attach(5); // attaches the servo on pin 9 to the servo object
myservo2.attach(6); // attaches the servo on pin 9 to the servo object
}

void loop()
{

if (analogRead(A2)-analogRead(A3)>threshold)
{
myservo1.write(90);
delay(15);
}

if (analogRead(A3)-analogRead(A2)>threshold)
{
myservo1.write(-90);
delay(15);
}

if (analogRead(A4)-analogRead(A5)>threshold)
{
myservo2.write(90);
}

if (analogRead(A5)-analogRead(A4)>threshold)
{
myservo2.write(-90);
}
}

This is the monster in all its tentacularity:

****

Testing the barebones circuit with the solarbotics white DC gearmotors and the SMD solar engine. It works with only two mini solar cells and the SMD cap as long as the sun is medium strong!

 

This is exciting as a result (but I just needed the change the motor wire polarity):

Here’s what the circuit looks like:

This suddenly stopped working and I did the following things:

Checked to see if the cap was charging, if the voltage monitor was triggering (and I manually triggered the MOSFET to see if the motor fired), the voltage at the midpoint between the two photodiodes, and if there were any shorts.

In the end I replaced the zener with a normal SMD diode which I found, replaced the photodiodes with green LEDs because one lead was broken on the photodiode, and then discovered the motor was broken (or at least the blue wire was disconnected on the inside)! It gave me a chance to look inside the tiny gear boxes of the motors though: 

Here is the, once again, working prototype:

 

I would like to be able to tune the midpoint between the LEDs. I would also like smd light sensors. 

Phototransistor Output Voltage Circuit connects the phototransistor and 2 k-ohm resistor in series

Some options for solar panel and motor assemblies:

Here’s with SMD LEDs soldered on:

Not sure why but the thing is only turning clockwise…

I tried the following things:

  1. A 10K trimpot (with each photodiode into each side of the resistor and the variable pin going to the logic chip). The trim pot at either extreme does indeed make the circuit turn in the opposite direction. However, in the middle it stops either side from firing.
  2. Replacing the photodiodes with Silicon PIN Photodiode BP34s, green LEDs 5mm, Green SMD LEDS, and LDRs.
  3. changing the ground of the photodiode pair to the ground of the capacitor instead of the ground connected to the floating connected to the MOSfet.

Just found this image here (http://solarbotics.net/library/circuits/bot_popper_240.html) which seems to imply I could use phototransistors also:

Looking at other Smart Head circuits, it looks like the + side of the photodiode pair is connected directly to the Vcc but that the negative side is connected to the “local” ground, not the negative of the capacitor. However, there are also counter examples…

I tried just setting up the dual photodiode circuit on a breadboard. Two photodiodes , two LDRs etc. They each move from a midway value up or down depending on which device is in the dark. However, they don’t always have 1/2V as a midpoint, which appears to be the important threshold point for the oscillator. **EDIT** I think what they meant was half of VCC not 0.5V. I could try to find the exact threshold voltage that is the balance point with the power supply?

2.25V for my desktop breadboard version of the circuit while supplying 4V for the solar panel. 2.85V was the threshold with solar panels at 5V. It also has a dead zone where neither motor will fire if it is perfectly in the middle. 

For the soldered version the threshold is around 1.3-1.4V when being fed 4V as solar panel. 

At 3.5V solar panel supply, I have a lower threshold bound of 1.25V and a higher bound of 1.4V. In the deadzone neither direction turns. 

At 3V funny things happen. It will only turn one direction unless I suddenly make the input 0V. This might explain why my circuit is behaving strangely! I am using a 2.92V voltage supervisor so I don’t think my current circuit is ever going to work. 

I should replace it with a higher voltage threshold like this one perhaps: https://www.mouser.fr/ProductDetail/968-ISL88001IH46ZT7A 

In the meantime I can use a voltage divider like I did for the 1381. 

Here’s the scope output attached to one lead of the motor. The fat, fuzzy part is when the motor is not turning and the threshold is reached. Either side it sends between 1.5-2V to the motor turning one way or the other.

Setting up my own little trim pot between the LDRs I was able to tune them to the correct voltage threshold and everything works well on a breadboard at least.

Here is the 74AC240 datasheet: 

Checked out the 74AC240 datasheet, for 3.5V the threshold should be between 0.9V-2.1V.

****

Version 2 of the board has trimpots for the voltage trigger and the light sensors (which are now SMD and on either side of the board):

Here are the parts laid out with the new board:

Post-soldering. The size of the board versus two small solar cells:

I had to put electric tape under the trim pots because contacts were exposed underneath…  The full assembly:

****

Found this online here (http://www.smfr.org/robots/robot_images/dualsolarhead_schematic.png): 

It uses the solar panels as the light sensors! It also lays things out in an easy to understand way (the midpoint is the boundary between what the inverter sees as HIGH or LOW. Once the solar engine has enough power this decision of HIGH vs. LOW then powers the motor through six remaining gates – presumably to increase the current as each pin seems to be limited to 75mA according to the datasheet above?).

***

Testing V.2:

I can get 3.5+ volts (4V outside in full sunlight even) with the current setup of two solar cells + little cap!

BUT…When I short the voltage supervisor 5K trim pot the motor fires, but even in its least resistance position the supervisor is not triggering…It is also only doing mini movements, not full shots. I removed the trim pot and now it behaves normally. I don’t understand why the trim pot doesn’t work when it was flawless with the benchtop power supply…

With a 1M trimpot the variable voltage trigger does work just as expected, however! I moved it up to 3.5V ish.

The 5K trim pot for fine tuning the light sensors also does not appear to work. Also doesn’t work with a 1M and two green LEDs…

I tried using the two solar panels as sensors as suggested in the found circuit and it appears to work, there remains the same problem of how to tune the voltage level however if my trim pot solution doesn’t work. 

***

I think I need to order 74AC240s (I think the 74LS540s I am using might be slightly different in terms of their HIGH/LOW thresholds) or voltage triggers for 3.5V+. This is a nicely tuned circuit that seems hard to mess with.

Just a reminder of how much the complexity has been reduced in this project!:

***

I have realized I need to understand the circuit I am working with better in order to tinker with it. 

First thing, the 74LS540 that I am using has a minimum voltage of 4.5V! It also can only supply 45mA max as an ouput if I understand correctly. However, I also have a 74F244D octal buffer which works as low as 2V. However it is Bipolar and not CMOS technology like the 74AC240 AND more importantly, it has non-inverting outputs. Clearly getting the right logic chip and family is an important element and not a detail for this circuit…

So, the LDR “photo bridge”. After testing 10 we had lying around I arrived at these average values:

 

Here’s some R Thevenin calculations (Thanks to Learning the Art of Electronics!) to figure out what size pot I can afford to pull up or push down the midpoint from the LDR divider:

 

And here’s the current logic circuit in a more understandable format:

****

Did some tests, looks like I need to bring the midpoint DOWN in my circuit:

Yellow is the cap voltage (3.42V) and green in the midpoint (2V) with equal light on both phototransistors. 

This scope image shows first both photodiodes in light, then the left (connected to GND) in darkness, and finally the right (connected to VCC) in darkness:

Without even needing to take any measurements it’s evident that the midpoint is too high. This causes the motors to always turn the same direction when the light intensity is equal between the two phototransistors. I flipped the photo transistors and observed the same effect so I think it’s the circuit not the difference between the phototransistors.  

This scope image shows me adjusting the phototransistor trim pot. (Fully attenuating on the left, halfway in the middle and then fully open on the right). 

And here’s testing with the middle threshold covering and uncovering each phototransistor:

This shows that the 10K trimpot effectively drops the entire midpoint! I can effectively dail in the midpoint to exactly half of VCC now (3.42 Vcap, 1.71V threshold)!:

Now the machine is not turning in only one direction! But it also might need some resistors for when the two photodiodes are both seeing bring light. I also need to replace the LS540 with an AC240 because I am currently operating outside the maximum minimum voltage of the IC. It would also be nice to use the solar panel as a sensor and thereby reduce the part count (I could still tune the midpoint in the same way once I determine which way the imbalance is – it would also solve the shorting problem in high light). 

I varied the pot and everything is working as expected. I also added heat shrink to the phototransistors. Here is a video:

I tried some 2DOF designs but I think this needs to stay MINIMAL and the force of the project, if it comes, will come from the array more than individual complexity. Plus they already seem imbalanced and more likely to malfunction…

Some tests with the solar panel voltage divider:

Here’s what it looks like when I change the solar panel midpoint with the 10K trimpot:

Here is the solar panel midpoint trim pot all the way to one side:

Here is the solar panel midpoint trim pot all the way to the other side (not sure why it goes all the way to the ground here only):

Here is me putting one panel in the shade, then the other. The difference is not massive.

The problem is that now I fall into a large deadzone where no movement happens in the middle. I’m trying to find the right combination of voltage trigger trim level and solar midpoint level but it’s not easy without sunshine…

****

Here’s the cost per unit of this design:

74AC240: 0,462 €

0.2F cap: 1,21 €

solar cell: 3.56 € (1.78 € x 2)

micro gear motor: 4.25€

voltage trigger: 0,356 €

diode + 0.47uF cap: 0,1€

PCB: ?

Total: 9.938€ + PCB cost

****

I have now a 1M trimpot on the solar midpoint and have added a 1M between the midpoint and VCC to try to balance things out.

I think 3×3 is better than 4×4 ? 5×5 would be out of control.

****

Working towards simplifying the dual servo sun seeker. Here is a post for controlling servos without a microcontroller:

https://www.pololu.com/blog/18/simple-hardware-approach-to-controlling-a-servo

Could use LDR pair to replace pots inside the servos, based on ideas from Hackaday post shared with me by Paolo Salvagione:

Light Tracking Robot Relies on LDRs

 

***

Went back to the super simple business card sun shaker and added some feet. I also tested the new 0.2F caps and they work with outdoor light but might be too tough to charge with indoor light (unless it’s actually bright then they work fine). After Paolo Salvagione’s comment about using a smaller motor to rotate the device, it occured to me that I could use the vibe motors in two directions to create movement that follows the sun:

 

****

Ordered this motor: 

Here is a new design with (human) adjustable tilt. It has more of a “pro” vibe. The motor adds 5 euros to the total cost of the machine bringing it up to 15 euros:

****

Looks like the trick with the light sensing is just to put the photodiodes behind the board so that the shadow cast by the sun creates a clear preference for one side or the other. They can be bent around a little bit to be perfectly tuned but it also adds a bit of idiosyncracy to the ‘bot. So it doesn’t appear that I need a trim pot for this option. I’m not sure how to create the same contrast with the solar panels as putting either in the shade is obviously not a good idea. Pointing them in different directions creates some difference but not a great deal.

****

I’ve redone the circuit for the 74AC240 and make it more compact:

Here is my next design with the smaller DC gear motor. I’m imagining a soldering a pin to the PBC in order to attach the pivoting arm to it. Otherwise the issue is how to make this attachment without creating a whole frame and bumping into components etc. It has a small M2 bolt to fix the print to the motor and to adjust the angle:

I’ve made a cleaner video of the first prototype:

Dual Solar Tracking Part II

Continuing the project of making a small solar tracking device.

****

Idea to simplify the circuit drastically and make the 3D model a bit more robust and less fragile so it is far easier to assemble and won’t topple over (while hopefully maintaining some elegance…) 

-Battery-powered (and possibly solar recharging through very simple circuit):

 

plus Attiny with two steppers only powered directly from output pins (max 40mA and danger of kick back which might be solved with diodes) and no light sensing – just the almanac algorithm for sun following. *

*(Remember you can test the stepper resistances to know which are pairs!)

Tried powering a stepper directly with an Atmega using the Stepper library in Arduino with a bunch of different step and speed values – if it turns at all it’s extremely weak…So this doesn’t appear to be an option.

Tried powering an atmega328 directly to cap and solar panel through diode, in medium sun there is no action. With bright sunlight it manages to power up despite blinking a blue LED every secon. I could try with the sleep timer I recently acquired (https://www.adafruit.com/product/3573). Or maybe a simple sleep code will be enough. This seems like a viable option which would simplify the circuit considerably.

Another cheap and simple option is the ULN2003, but this requires 5V to function unlike the low power DRV8833 I have. 

***

Tried driving the stepper gearmotor chain drive and it moves very smoothly and almost imperceptably. 

I dug up some DC DVD raft drives, they are nice mechanisms:

The black rack was attached to the raft. 

I tried powering these with Wilf’s SPSH circuit and the bearbones solar head and they were too big a motor to be powered unfortunately. I could still try to increase the 1381 trigger level with a resistor though…

I’ve redesigned the microchip version of the board to make the wiring to the stepper much easier this time. I’ve also added two caps to smooth out the motor supply. 

And here is a more robust version of the previous two stepper, this one has two parallel bars, a more robust hinge, and the lower bearing is encased completely for more stability hopefully. I am also getting rid of the lead screw plastic piece and trying to replace that part with a thin metal rod. In general it’s simplified and a bit thicker all around :

I am using a dremel to clear out the holes before inserting things and this is reducing shattering of the more fragile white resin. 

The bottom bearing:

Part of the solar panel hinge:

Only one of the two stepper drivers worked on this board but I haven’t found the issue yet…I wonder if back reverse polarity I destroyed it by accident or over heated it during soldering. I’m going to replace it with a fresh one and see if that changes anything.

 

Here’s the assembled machine:

Here is a look at some of the technical details:

 

A different panel orientation option: 

Comparing the two versions (the newer is far more compact and stable but less playful and off-beat/asymmetrical):

Check out the angle range, it’s better than I expected!

ERRATA:

  1. The idea of putting a pin accross to act as the lead screw is not working with only one side screwed in. AND the lead screw platform is impossible to insert into position (I had to break it in half and glue it back together once in position). I should definitely not try to go under the lead screw, with the nut that holds the pin, it actually makes contact with other nuts holding the whole linear rail assembly. I think I should go back to integrating the existing plastic lead screw – aesthetically it adds more flavour and asymmetry.
  2. The part that attaches to the panel should be one connected part because this gives more surface to attach to and more rigidity. (X)
  3. There is a volume which enters into the bearing socket that I needed to remove with the dremel. (X)
  4. The three bottom holes for screws are not evenly spread out around the circle. (X)

POSSIBLE CHANGES:

  1. Tensioner for bottom chain or larger bottom gear?
  2. The top hinge is too symmetrical for my liking but otherwise it’s super stable.
  3. Transparent resin is definitely nicer.
  4. The bottom nut needs a tiny bit more room, but it just works.
  5. The bolts are hitting the bottom stepper gearmotor.

Here is a new version which solves the errata, but it looks hideous:

I am considering returning to a one bar setup. I am also considering how I can make one version of this device that will work for the different linear actuating steppers and the different rotational motors (the micro steppers and DC gear motors have the same face plate thankfully). The top and bottom of device are also not connected (so varying heights of linear drives can be accomodated). Should one single design be able to work with belt drive or chain? I think I should now focus on producing a bunch of these.

Here is how the little plastic parts that act as lead screws work:

 

There are all kinds of shapes but in the end they all appear to have one main screw location and a bunch of other nibs and slots to help with alignement. I can include a sliding slot for the main screw in the 3D print but I may use a dremel to adapt it to different nib locations. 

I’ve revisited the version 1 and have made the following changes:

  1. I’ve kept the more robust base from version 2.
  2. I’ve revised the lead screw plastic part holder and made the print compatible with the highest number of these peices and allowed for longer stroke.
  3. I’ve kept the magical setup that allowed for a great variation in the panel angle.
  4. I’ve kept the circular base which is more stable and made a larger base gear so it looks more stable. (The pitch of chain I am using is 0.1227″ https://www.mcmaster.com/miniature-roller-chain-sprockets/pitch~0-1227/)
  5. I adjusted the motor so the bolts are no loner hitting the bottom stepper gearmotor.

 

****

Wire management:

I like the ribon wires from the CD drives and the mini locking sockets and plan to use them:

The top option seems sensible.

Here the bottom motor ribbon is going to be super stretched when the panel is at full extension in angle…

I like the asymmetry of the second option, it implies that the lead screw and hinge action is taking place on one side and the electrical connections on the other side.

(I’m just realizing that some of the ribbon cables that come with the stepper linear drive are not very long + the brown/orange doesn’t go super well with the white. Should I replace those cables with white ones so that everything is the right length and homogenous?)

 

There is also the possibility of folding the ribbon cable…

I’m trying to find this product (it seems to be called “flexible flat ribbon cable”) but not having luck on Farnell or Mouser (*correction: https://www.mouser.fr/ProductDetail/Wurth-Elektronik/687606050002?qs=qR1qlUC5%2FYSp8nXHAtNchQ%3D%3D) …Here it is on Ebay and Amazon:

The other option is to harvest wire from the old CD drives I have, the wire lenghts seem to vary from 8-11cm.

Some solar panel options:

 

****

Next version sucesses:

orienting parts so that the supports don’t touch faces that will be seen is a good idea, it saved the bottom platform from pockmarks.

Errata:

  1. The main issue is the lead nuts. They are massive and therefore reduce the stroke considerably. Most have a setup where they push against the leadscrew and twist the sliding cam which is now only fixed to one rod.  I should try to design the nut myself, if the solar panel is in the middle it is hidden in any case. The other option is to find another one in a million lead nut that works like the one in version one where it doesn’t push against the cam / use two bars. (X)
  2. Somehow the ratio of arm lengths is producing a totally different range of angles, mostly in the negative direction! (X)
  3. the layer on top and below of the bearing is too thin and comes out wavy. (X* I did the top visible part but not the bottom).
  4. missing a subtraction around the collar of the bottom stepper motor shaft. (X)

Possible changes:

  1. all black hardware would be nice. Or perhaps all white?

******

Modeling the lead screw:

The threads themselves:

I want it to be possible to adjust this thing so I am planning to use a stack of washers to accomplish this. I am also adding a notch in the purple volume to prevent the green volume from rotating. It should also mean that the green volume can be made to accomodate different threads and the purple volume will still work regardless (i.e. it’s modular).

The backside leaves space for a nut to fix the green piece in place at the right height.

I’ve also adjusted the angles to match the version 2 as exactly as possible this time:

Here is the finished version 3:

Some quick ideas about how this project could be displayed in an expo:

1. I can make a bunch of solar critters that react to the sun in different ways (sweeping in circles, following the sun but staying in place, making sound by tapping the ground or playing a song, etc.). This is the kind of ludic, “diversity of nature” bio-inspired option. The robots are indifferent to one another but occupy the same space. I’m not sure how to chose the materials but maintain difference/cohension of the group but presumably I could pick a kind of 3D printing and use the same motors.

 

2. Make one such critter (like the sun follower) and create an array of them in a given space and watch the group effect of their behaviour. This is kind of obvious but at least it’s abstract and sober, hopefully fitting in my portfolio with my other more abstract/representational work. It would also be easier to mass produce one design than to make a bunch of one-off designs I think.

And here is the BOM so far:

And here is the newest build:

ERRATA:

  1. The lead screw does not work. It is not perfectly aligned with the threaded rod and the system for holding it tightly in place is not working. I think I need to put the lead screw on the bottom side of the threaded rod and have a tensioning mechanism on the front (accessible) side.
  2. The angles are still wrong. If I make the top arm (that is glued to the solar panel) shorter I think it will improve.

I’ve put the lead screw on the back of the threaded rod and inserted alignment rods and increased the borders to hold the top piece in place:

****

The solar panel angles are fixed! With two of the threaded nut sides making a sandwich it does actually work as a lead screw nut (even though it really doesn’t look nice) !

***

Thoughts from artist Paolo Salvagione:

  1. Make a power budget (what does everything i.e. steppers, microchips, drivers use when not on, when on)
  2. Run motors 24/7 for weeks before to test that nothing falls apart.
  3. Replace bolt hinges with flanges or miniature bearings from McMaster Carr. (The smallest available at a reasonable price is 5mm OD no flange).
  4. Try pulling up everything to the top beneath the board and alternatively pushing everything else to the ground to create a sunflower.
  5. Think about the center of balance of the machine and how you can place it directly over the pivot point (or move it there with weights).
  6. What kind of choreography would I like to see here.
  7. Alibaba has super inexpensive solar panels that look great.
  8. Could the array relate to different light sources which exist in a kind of solar system around the plinth.
  9. How can visitors experience this piece at different distances (“layers” of experience)?
  10. Medium-runs of a finished design are easier than making a ton of one offs or mass producing.
  11. It’s possible to order flexible PCBs from PCB Way.

****

Some thoughts on the layers possible:

I have found a few 10mm OD bearings and will redesign the arm portion with these:

I’m not totally satisfied with the bearings in the design (McMaster has perfect 5mm bearings that are reasonably priced but they don’t ship out of the U.S.).

****

Calculating the balance point with help of this site: https://www.school-for-champions.com/science/gravity_center.htm#.X2B-cFUzaUk

Calculating CG of weights 

CG = (aM + bN + cP)/(M + N + P)

Seems like I should try to keep the solar panel light in general (under 12 grams?), but that I have the option of adding some weight above the stepper in the rear. In the other axis I can shift the solar panel a bit to the side to compensate for the weight of the bearings in the arms. 

 

****

New version with arm bearings:

It was hard to attach the solar panel to that arm model so I switched it for one with mini bolts:

   

I don’t like the look of the three wide and narrow bearings so I am trying to hide one under the panel and switch up the second by putting the black bolt through it. One of these only would look great but three is too much.

 

A new design with McMaster 5mm bearings (I can in fact order them it would appear). In one I keep a single large bearing and in the other all the bearing are small:

Making a third prototype to test the following things:

  1. Durable resin for everything but especially for the lead screw.
  2. Adding flanges to hold the current bearings in place.
  3. Slight tweak to the currently improvised lead screw design.
  4. Fix angles again with shorter arm.
  5. Hiding the other bearings a bit under the panel.
  6. Making a third so that I can begin testing the “swarm” effect of the robots actually moving.

****

I began two stress tests based on Paolo’s advice:

Some things to note:

  1. These are so much fun, people visiting see what you’re doing as Paolo suggested!
  2. It fights anxiety – you know if it will work or not.
  3. Working for 1 minute is not the same as working for two weeks 😉

Unfortunately there is a serious issue: The linear drive is drawing 600mA at 5V to move up and down…I should try to mess with the steps and speeds to see if I can get this down. The rotating motor is drawing less than 150mA. 

Looking on Alibaba, the most popular size of smaller panel is 156mmx156mm.  But also found some 47×47:

and some 55mmx14mm

37x21.8mm 6V 2mA outdoor used Thin Film Amorphous Silicon Solar Cells for Outdoor Products

37×21.8×1.1mm 

Here are the best links I’ve found so far:

https://www.alibaba.com/product-detail/55x14mm-3-0V-7uA-dim-light_60585863880.html?spm=a2700.galleryofferlist.0.0.43be4630X6CXwJ

https://www.alibaba.com/product-detail/Dim-Light-Amorphous-Silicon-Thin-Film_208238751.html?spm=a2700.details.deiletai6.5.561929devzX1BP

https://www.alibaba.com/product-detail/3V-10uA-Dim-Light-Amorphous-Thin_62187655652.html?spm=a2700.details.deiletai6.1.561929devzX1BP

https://www.alibaba.com/product-detail/37×21-8mm-6V-2mA-outdoor-used_60506651563.html?spm=a2700.galleryofferlist.0.0.2430367cO11E7R&s=p

 

I sent my first email: 

Hello,

I’m a research engineer at the Universite of Paris Sud in France and an M.I.T. graduate.

I’m working on a low-power solar follower product and reqiure small cells like yours to create a series of panels (with each an array of 5×2) to combine with an energy harvesting IC.

I am interested in your product and would like to request a sample if possible to test with my setup.

Thank you ,
Jonah Marrs

*********

Easy stepper motor driver can drive both steppers at around 150mA at 5V with no load. 

The DRV8833 with correct step and speed settings can drive the linear with the plastic lead screw found in the CD drive at around 360mA but has a super high idle current of 600mA. It gets super hot as a result. The DRV8833 cannot drive my lead screw setup however… Basically there is too much friction in my lead screw design currently. So, the conclusion is that it’s possible to drive this thing if I put the driver to sleep and I use the existing lead screw.

I am leaning towards using the found CD drive mechanisms (because they are perfectly made to minimize friction etc. already and look super cool) and add a second bar parallel to the first to improve stability and compensate for the rotating that the plastic lead screw wants to do.

I’m also adding another bolt to the bottom angle bearing, and looking for some 3mm bushings to add to the sliding portion. Here seem to be the two primary options:

The side by side bars on the left are less flexible with different found lead screws as the bolt location can’t move much to either side. It also makes the front part flatter and longer, whereas the bar behind makes the design feel more three dimensional and compact. 

I prefer the bar behind. 

Bending joints options:

I like the asymmetry of not having the top and bottom joints unaligned in elevation and in plan views, it feels more dynamic and optimized. I like the bottom bearing being centered with the cam. 

Hopefully this version will allow me to do some stress testing with the tilt mechanism.

 

Here are the parts laid out:

The assembly turned out well:

 

ERRATA:

  1. The lead screw is a tiny bit too high above the threaded rod, I had to carve out some material with the dremel…
  2. The elbow joint connected to the cam can’t work with a captive nut the way I originally concieved but it can work with the cap of the screw in the place of the nut.
  3. The set screw for the sprocket needs to be almost flush with the sprocket surface to not hit the bearing squeezing screw. The bearing squeezing screw between the parallel bars needs to come from the top not the bottom or else it interferes with the chain. 
  4. I think I need to shift the two bolts that hold in place the bottom motor 90 degrees. And I may need to add a little circular band to keep this motor straight.  A tiny drop of hot glue solves this…
  5. The solar panel surface is not flat but tilts inwards.

I got the test set up working again with two Easy Stepper Motor Drivers (with Enables and 5V+ connected also) this time. Now the bottom motor is driving 100mA and the linear is pulling 200mA. Both are cool to the touch. However, there is a little bit of power lacking for the linear lifting motor and it is skipping some steps. Switching to 1/4 instead of 1/8 microstepping, and making sure all the bearings are set up smoothly, appears to mostly fix this though.

Some experiments taking nicer photos:

A with and without solar panel gif:

*****

I’m doing a next design based on the observation that the motor is struggling to pull up the solar panel and that the weight could be repositioned closer to the center of gravity and rotation axis. It’s more sunflower like, and the lead screw is now exposed as in version one. Nicer balance in terms of the bending joints which now aren’t all on the same side. One of the three bearings is hidden so the emphasis is more on the two side ones now. Far more sturdy rotation mechanism for the solar panel so no more warping and bending hopefully. The arm will have to travel far less distance to change the angle of the solar panel also.

This experiment is interesting to me because it’s an attempt to move towards a more robust design while trying to keep it visually interesting and maintaining the attention to form.

 

I adapted it for a mirrored version of the linear drive and new lead screws (it wasn’t too hard to do). Now I have right and left handed machines:

This is interesting as it shows how easy or not it is to adapt to the repurposed CD drive mechanisms with the current design and how much variation can be created organically. 

***

 

It looks like I should go with white Rigid resin and that I should use bushings for the sliding portions so no part of the print has friction.

These appear to be the key characteristics of the lead screw/nut setup.

****

Adding some grease to the rails:

*****

Here’s the tall version:

It has great tilt range.

It feels much taller and more slender. It also looks far more like a sunflower. It’s also lost its animate / cuteness quality that comes from being compact and now feels more like a machine. It does make more sense in terms of weight distribution, however.

It proves that the idea of adjusting for found CD drives works in principle. 

V.4 ERRATA:

  1. The Durable resin is too flexible to make rigid longer parts. The whole assembly is flopping all over the place.
  2. I need to modify the central solar panel hinge – it’s not possible with the hardware I have to make it function properly. Because the tilt arm pulls from the side, it has a tendancy to tweak the central hinge. I could use the large bottom bearing up top?

****

The new version features a pole that pushes up to tilt the solar panel, and lets the panel rotate down when it descends. This means fewer bearings and maybe less strain on the linear actuator stepper motor:

I’ve redesigned the control board. It now has a nicer spacing between the motor driver out pins and doesn’t have any other wires nearby to get in the way of these pins. It also has the motor driver sleep pins connected to the microchip, and can drive two steppers instead of one stepper and one DC motor as with the previous version. It also has more noise attenuating caps:

I am also considering using an Arduino Nano with DRV8834s and a mini lithium ion just to get this prototype running!

This works but it’s very heavy with the battery packs. I may need to glue the bearings in place or work with a more robust design for this phase.

 

I’m using the StepperDriver Arduino library and this is what my loop looks like:

if (analogRead(A0)-analogRead(A1)>threshold)
{
stepperTop.move(-MOTOR_STEPS*MICROSTEPS);
}

if (analogRead(A1)-analogRead(A0)>threshold)
{
stepperTop.move(MOTOR_STEPS*MICROSTEPS);
}

if (analogRead(A2)-analogRead(A3)>threshold)
{
stepperBottom.move(-MOTOR_STEPS*MICROSTEPS);
}

if (analogRead(A3)-analogRead(A2)>threshold)
{
stepperBottom.move(MOTOR_STEPS*MICROSTEPS);
}

 

And here’s the new print:

****

Just discovered why I may have been having issues with the DRV8833s…Their max soldering temperature is 260C, I have been using 300C!

****

I tried to get a full prototype running with the Arduino breakoutboard version but it’s surprisingly heavy and both attempts were unsuccessful. The second:

Without the weight of the circuit board everything is fine however:

 

I think I may have to admit that this thing is too janky to work beyond as a quick video. 

 

*****

Meanwhile I’m working on a DC prototype of the more complex 2DOF design:

 

The idea here is to have 2 1DOF solar engine circuits + a dark activated pummer circuit. The machine would then spend its days searching for the sun and charging up a bigger capacitor to then blink at night like a lighthouse. I’m not sure if I should make the blinking synchronise with other nearby blinkers using this circuit:

https://www.instructables.com/Synchronizing-Fireflies/

One DC motor (controlling the tilt) is so slow it’s barely noticable at all while the other one swings the machine round dramatically. The design has less magic than the servo version but is far easier to control and has no issues with the weight of the solar panels. 

 

Robot Arm

Here is the final product:

 

 

1 Common robot arm configurations | Download Scientific Diagram

After the relative success of the foam cutting machine, I would like to build a medium-sized robot arm which can actually be a useful tool in the lab and not just a toy.

The main questions appear to be: how to increase the torque of the stepper motors? Should we make a classic robot arm or a Selective Compliance Assembly Robot Arm SCARA?  Should the parts be 3D printed or CNC milled (or a combo)? and, Do I already have the parts necessary or do I need to order them in which case how much should I order?

**********

Stepper torque options:

1. Use our super beefy stepper motors. Unfortunately, none of the other hardware (like belt sprockets) fit the diameters of the shafts.

NEMA 34 Stepper Motor (6A , 12 Nm , 151mm) | DIYElectronics

2. 3D print a planetary gear or buy one:

(but these make the front of the stepper bulky and a bit ungainly)

3. Get a large timing belt pully with a short belt drive: (unfortunately we don’t have anything like this lying around the lab).

4.  3D print a large gear to turn directly with the stepper:

A different concept that involves a motors not all at the base:

**********

SCARA vs. Conventional robot arm.

 

Building SCARA Robot Arm pick and place using vision system - YouTube

YK400XE

#SCARAs fold up easily and are faster for certain tasks than conventional robot arms.

 

pyBot: OPEN SOURCE and 3D printed Robotic Arm controlled with Python

Custom SCARA printer finally taking shape. : 3Dprinting

Scara arm solution

A Desktop SCARA Robot using Stepper Motors

298 Best CNC images in 2020 | Cnc, Diy cnc, Cnc machine

But there are some neat conventional robot arm designs out there too:

*******

CNC milling vs. 3D printing:

CNC milling some parts (like the large gears) seems possible:

Nylon and ZMorph CNC PRO Milling Toolhead

But I also need either to buy a large bearing or to make my own bearing…Unless I make a geared slew bearing:

Single Row External Gear Slewing Bearing China Manufacturer

Here’s a cool guide on designing gears: https://lcamtuf.coredump.cx/gcnc/ch6/

Some DIY slew bearings:

Project | Mammoth ARM | Hackaday.io

A 2.5D Slew Ring | Hackaday.io

***********

Robot background information: http://www.societyofrobots.com/robot_arm_tutorial.shtml

Cool tutorial includes info about DOF, calculating torque for each joint (fewest joints possible with shortest lever arms the better): http://www.societyofrobots.com/robot_arm_calculator.shtml

Some simple arm linkage ideas:

Homemade Scara Robot Arm DIY Robotic Frame Projects Laser 3D Printer Chassis Draw Arduino Control d - YouTube

3D Printer Technology and Innovation | Desktop cnc, Robotic arm diy, Diy robot

**********

And these Five-bar linkage machines (aka Parallel SCARA robots), they appear to be known for being super fast:

https://en.wikipedia.org/wiki/Five-bar_linkage

Homemade Scara Robot Arm DIY Robotic Laser 3D Printer Chassis Draw Arduino Control Frame Projects 2 - FutureTribe.Me

SCARyllA: Dual (parallel) arm SCARA laser engraver build

ÉTS : Laboratoire de commande et de robotique

Related image

Lightning-Fast SCARA Robot Prototype by Proto G - Hackster.io

**********

For the end effector I think either air pressure or electromagnet:

Vacuum End Effectors VEE

Robotics Industry Insights - Latest Trends in Intellig...

************

Some early models:

With only two rails (I’m not sure if this is sufficiently stable or not as many designs have 3 or even 4 rail):

Similar but with a larger motor at the bottom and less ugly mounting plate. 

A completely different SCARA design, I like the silhouette but it would involve tons of cut planar material that would need to slide into together and we might not have everything on hand to make this either: 

Quick attempts at 3D printing planetary gears:

https://www.thingiverse.com/thing:2114390

https://www.thingiverse.com/thing:3231908

(interesting belt option here: https://www.thingiverse.com/thing:2911407)

Using the 0.8 nozzle was not ideal and none of the pieces fit properly. I would love to try this as a cnc cut project but I think it would be highly technical and difficult and at the end would end up in a tiny box. (I’m going for medium scale machines at the moment not tiny intricate things).

We have 12mm HDPE in white and blue in the lab, I’m going to first 3D print then mill it. 

I’ve come to a compromise with the design. It will give me the opportunity to design with a Nema 23 a complex peice (geared slew bearing), to work for the first time with a 5 linkage parallel robot design, to CNC mill HDPE for a more robust machine, but also builds on the syringe pump linear actuator and the foam cutter designs. Most importantly, I have all the components I need to build the full prototype already in the lab. 

I added hardware to this model to make sure everything makes sense:

*********

Developement of the geared slew bearing:

Outlined this drawing in Rhino and then applied it to a circle:

To make everything fit (increments of 2mm) I changed the size slightly of the gear:

 

Here is the first prototype:

Here is a section showing the bearings cut through and how two layers of 6mm HDPE should come together to make the bearing. After assembling we’ll see if .1mm was too much spacing between the bearing and the walls, and also if there need to be two rows of 4mm bearings.

 

*******

Here are the 5 bar parallel robot 3D printed parts (view from underneath):

A combination of nuts, washers, 16mm bearings and socket shoulder bolts:

There is an offset in order to make everything work on the stepper motor shafts:

 

*****

With the final additions here is the final machine:

Here’s the 3D print file with all the parts: 

Here is the kit of parts (minus the parallel arm rods):

The geared slew bearing assembly is tricky because the bearings want to fall within the inner moat.

Adding the top bit:

Finishing it off:

Here is the drive mechanism with an idler I added:

Assembling the parallel robot arm components:

Hammering in the bearings caused splitting in the print…

I sawed the metal bar and deburred before assembly. 

The top threaded rod motor assembly (I broke one side hammering the nut in a little too vigorously)  

Despite checking and rechecking I somehow forgot to put holes in the middle of the rod bearings (!)

Here’s the linear actuator assembly:

 

With the parallel arms attached, just waiting for the base to finish printing:

With the base:

 

Errata with the bottom part of the robot:

-impossible to tighten hex nut to fasten gear to bottom motor axel. (Added slot for this purpose)

-not nut subtractions to help hold bolts which fix geared slew bearing to base plate. (Added captive nut subtractions to bottom of base plate)

-I subtrated a cylinder from the base for the motor gear but this makes no sense as it rotates around and does not stay fixed. (I filled this in)

-With current arrangement the belt between the drive shaft and geared slew bearing was loose. (Either I add a spot for an adjustable bearing or I change the location of the motor to pull it further away…I chose the latter).

****

CNC milling:

The top motor and rail mount:

I replaced one part of the 3D printed robot parts at a time:

The middle component:

Everything fits together nicely!

And here is the final result:

The CNC mill using HDPE is extremely fun to use. The only part that is not easy to make is the bearing assembly. This I will print in durable white resin on the Formlabs.

    

Medium-sized CNC Foam Cutter (with Léon Reboul)

Here is the finished product:

 

And here is a quick video cutting foam:

 

Another video showing the stage testing:

 

 

Here are the files on Thingiverse: https://www.thingiverse.com/thing:4428184

We’ll be harvesting parts from an old Ultimaker 2.

The stuff we plan to use:

Based on what we found, we plan on making two threaded rod actuators and two belt-driven actuators.

Here is the prototype of the linear threaded rod actuator:

Here is the prototype of the linear belt-driven actuator:

Here is the prototype of the entire foam cutter assembly:

 Here are all the parts 3D printed:

Here are the 3D printed parts along with the hardware:

Here is the belt drive assembly:

 

Here are the two axes completed:

Here is the first of the two linear actuator drives:

Slight differences between the two based on different hardware but essentially the same:

Here is the full assembly minus electronics:

The electrical connections to the TinyG:

All plugged in and ready to go:

 

Using the webpage CNC controller Chilippeper :

Running local JSON script to allow the website to access the COM ports, if I understand correctly:

 

Chilipeppr Configuration (https://github.com/synthetos/TinyG/wiki/TinyG-Configuration-for-Firmware-Version-0.97):

To change the Motor – Axis assignment in Chilipeppr:

$1ma=0 Maps motor 1 to the X axis
$2ma=1 Maps motor 2 to the Y axis
$3ma=0 Maps motor 3 to the X axis
$4ma=1 Maps motor 4 to the Y axis

To assign the same travel per revolution for axis 4 as for the other 3 axes:
$4TR 1.25
To swap polarity of a motor:

$1PO

  • 0 = Normal motor polarity
  • 1 = Invert motor polarity

To set X axis minimum and maximum end stop limit switches (the switches connect GND to XMIN or XMAX on the Tiny G).

$XSN 3 and $XSX 3

To change the distance for every movement of 1mm:

$1tr VALUE

To change max feedrate in X:

$xfr

*************

Here is the video of the machine making its first moves:

**************

Here is a version two fixing some errors in the 3D modeling:

Linear actuator redesign (forgot to subtract the motor and threaded rod previously):

Here’s the finished belt-drive assembly:

I reprinted this part with 40% density instead of 20% (which broke last time when I tightened), corrected the diameter of the rods (which destroyed the rigity of the actuator), reoriented the embedded nut, and used shorter bolts:

Also 40% instead of 20%:

This was a bit tricky but using two bolts with washers I replaced the hot glue to fix the belt in place. 

I corrected the orientation of the holes and the two actuators line up perfectly:

Here’s the final assembly version 2:

 

*************

I’ve added some limit switches and have a preliminary setup for the hot wire cutting fixtures:

**************

Here is the first test cut:

 

Here’s what it looked like on the software side:

 

I used CAMBAM to take in a DXF and output the Gcode. 

I had to additionally make everything related to the Z axis zero, and set the start point.

DIY Centrifuge

Based on Hackteria’s DIY Centrifuge (https://hackteria.org/wiki/Hacked_Hard-disc_Centrifuge)

Controlling a Three-Phase DC Brushless motor (BLDC) of a Hard Drive primer: https://www.monolithicpower.com/pub/media/document/Brushless_DC_Motor_Fundamentals.pdf

Similar to a stepper motor (except a BLDC is meant to run smoothly not in steps) but with three stators (if it’s an inrunner, an outrunner has the permanent magnets around the shaft): 

What are Brushless DC Motors | Renesas Electronics

 

At the top are the signals we need to generate with signal phase 120 degrees offset (steppers are typically two phase with 90 degrees apart):

BLDC Motor Control With Arduino, Salvaged HD Motor, and Hall ...

I’m using the SN754410 Quadruple Half-H Driver IC based on this tutorial: https://elabz.com/bldc-motor-with-arduino-circuit-and-software/

Here’s the circuit breadboarded (motor connection not shown) with a pot to change the speed:

Here is the scope capture of the sigals generated:

This is the 3D file I downloaded: https://www.thingiverse.com/thing:2539744

Here’s the 3D print with two 1.5ml Eppendorf tubes screwed on to the BLDC hard disk motor. 

I had difficulty distinguishing between which of the three wires were connected to coils and which on wasn’t and got inconsistent resistance measurements. My current thinking is that the motor was damaged and is not working.

Testing with another kind of BLDC and still not working…so is most likely my circuit?

EWOD (electro wetting on dialectric)

This project is based on Gaudi Lab’s OpenDrop (https://www.gaudi.ch/OpenDrop/)

Here is the github for Fablab Digiscope’s iteration of the project: https://github.com/merlinmarrs/OpenDrop

We don’t have high voltage MOSFETs so we are using relays instead. In parallel we will be sourcing the components to make the high voltage power supply using a boost converter that takes 12V as input. In the meantime, we will be using a transformer that sources 100V directly to the board to test functionality. 

Here is the board cut:

To supply the minimum 100V necessary, I found this high voltage boosting circuit here: https://www.multisim.com/content/dUPNxLKfTuK3sYfGNjNxNg/9v-to-100v-boost-converter/

With what we have in the lab, it’s peaking at just under 80V. 

Testing the relay:

Testing the relay with a motor and 9V battery:

Here is the first full prototype:

 

What we need now is some hydrophobic dialectric like Teflon…

Fever monitor

This device is intended to be installed within the 3D printed forehead mount of a visor. 

It’s being developed at this github: https://github.com/merlinmarrs/Fever-Meter

The top board is a boost regulator taking the 2V from a pair of miniature backup batteries, and the bottom side is an attiny85 with I2C temperature sensor and indication led. 

This project necessitated the use of rivets. I used a dremel to make a hole in the board then inserted the rivet and gave it a tap with our riveting tool.

The results are relatively clean:

IR thermometer with POV display

This contactless temperature sensor has a POV display for the temperature readout. 

Here is the github: https://github.com/merlinmarrs/POV-fever-meter

Here is what it looks like in a dark room with long exposure:

The plan was to have the device spell out the message in reverse after displaying it normally to allow a certain frequency of waving the wand back and forth to display perfectly. Alas…this does not work well currently.

I am still waiting for the IR temperature sensor to arrive in the mail.

Dispositif Désinfection

Developed by Fablab Digiscope.

A board to sense the temperature and illumination, and act as an interface, inside a disinfection device:

https://github.com/merlinmarrs/anti-viral-dispositif/

A main board and secondary board to control a disinfection chamber based on this tutorial: http://www.needlab.org/face-masks-disinfection-device

Here is the BOM:

Standard components:

7 segment display x2 595 Shift Register x2 LED x 2 Photocell Piezo Atmega 328p micro-swith (CHECK MAX VOLT + AMP RATING)

exotic components:

lampe UV-C à Amazon.fr:

https://www.amazon.fr/Germicide-Ultraviolet-st%C3%A9rilisateur-Submersible-radiations/dp/B07Y82SM36/ref=sr_1_4?__mk_fr_FR=%C3%85M%C3%85%C5%BD%C3%95%C3%91&dchild=1&keywords=uv+aquarium+sterilizer&qid=1587383305&s=hi&sr=1-4-catcorr

  1. MLX90614 (pas en rayon a Mouser, Farnell, Sparkfun, Polulu ou Adafruit) à Digikey (ou c’est “hors prix”) ou Amazon.fr:

https://www.digikey.com/product-detail/en/melexis-technologies-nv/MLX90614ESF-DCA-000-TU/MLX90614ESF-DCA-000-TU-ND/2025323

https://www.amazon.fr/MLX90614ESF-MLX90614ESF-BAA-000-TU-ND-thermom%C3%A8tre-infrarouge-compatible/dp/B07JBKM2K3/ref=sr_1_1?__mk_fr_FR=%C3%85M%C3%85%C5%BD%C3%95%C3%91&dchild=1&keywords=MLX90614&qid=1587470750&s=hi&sr=1-1-catcorr

 

 

 

Still waiting for the temperature sensor to arrive in the mail. 

Syringe pump mechanism + electronics

 

This is the stepper motor driver design we are hoping to use to control a syringe. Here is the PDF describing the assembly: etapes fab venti v2

And here is the github repo:

https://github.com/merlinmarrs/FabVenti

 

This is the syringe pumping prototype I developed. It uses 8020, a NEMA stepper with built in threaded rod, NEMA motor brackets, and linear bearings. The rest is 3D printed and uses M3 and M4 screws. 

Solar Electronics Primer

The goal of this primer is to introduce people to mini DIY solar energy applications.

New solar product I just found out about: 

Solar Digital Calipers

                  

Fab 15 Part VII

Here are some videos of the current prototypes:

 

 

 

 

I want to focus this project on the design of the 2 axis rotation mechanism. The electronics and code side has already been explored and I can’t offer anything new here as a designer.

(I’ll abstract the sensing and radio side of thing for a now and design the PCB to be sent to manufacture later. This will be a good exercise in applying the new PCB design best practices that I have since learned and for overcoming the limitations of PCB making in the lab. I could imagine this board having a compass and accelerometer to find out its own direction, and possibly an wifi connection to send its data to the internet.

To simplify things further, I could think of this design as an indoor weather station. Instead of the tpical arduino inside a plastic box though, this project would emphasize the dynamic quality of solar energy, turning solar tracking into an exciting technical spectacle. The design would make reference to off-grid technology and thereby embody the mythical appeal of the power-autonomous and the off-grid (tiny house movement, prepper phenomenon, etc.).

*************

I’m inspired by weather buoy design:

 

And also the possibility of some kind of Wes Jones inspired multi solar panel actuated louver system:

Louver Dampers / Industrial Dampers • Kelair Products Inc.

It could look like the MIT solar panel project but it would have a lower center of gravity and be motor controlled.

Hyperstealth's "Declipse™" Shadow Reduction Technology Solves MIT ...

Some quarantine sketches:

*************

Problems with the previous prototypes:

V.1

Top heavy and always falling over.

Middle connection to ball bearing not sufficiently robust

Nothing keeping motor on track, it lifts up off the gear track.

Center mast not easy to fix in place.

V.2

Will topple over in certain positions.

Tilt cannot rotate 360 and is holding a lot of weight.

No way to tell exactly what position reached.

****************

V.3 Hinge tilt + 3D printed bearing with motor mount integrated

The hinge will be based on this idea from https://www.generationrobots.com/en/402702-pan-tilt-kit-for-pixy-camera.html:

Some detail shots of the assembly (from https://docs.pixycam.com/wiki/doku.php?id=wiki:v2:assembling_pantilt_mechanism):

Here is the one sided threaded bracket:

https://www.sparkfun.com/products/10228

Angle Bracket - 4-40

Here is a 3D printed version: https://www.thingiverse.com/thing:978300. I would be replacing the servo with the DC gear motor and changing the bolts:

And this is how the servo arm fastening works:

In combination with this is the idea to design a completely custom rotation system. This would combine Paolo’s 3D printed bearing mount (https://www.instructables.com/id/3D-Printed-Bearing-with-Driven-Miter-Gear/) with DIY stepper motor coils:

Image result for paolo 3d printed bearing

3D Printed Bearing With Driven Miter Gear

And these are two 3D printed stepper motors based on wrapping wire around nails and using rare earth magnets. I could also incorporate feedback by printing stripes and counting them with a line follower.

The only problem appears to be the voltage required to power these motors which seems to be between 5V and 20V. Perhaps I could take some industrially made coils (which would be presumably more efficient) and reuse them. Like from the inside of a real stepper motor:

Image result for 3d printed stepper

The magnetic field of a coil appears to be based on the coil density (number of turns per length of wire), the material in the middle of the coil (like iron), and the current passed through. I would need a dense coil if I didn’t want to drain the caps.

I could also work with small stepper motor linear actuators like this:, but then I would need to convert linear to rotary motion:

Image result for mini stepper motor

As for the code:

https://www.hindawi.com/journals/js/2019/3681031/

According to the above article, loading the Astrologer’s Almanac onto a sensorless microchip appears to be even more efficient than giving a microchip light sensors in the classic approach (https://create.arduino.cc/projecthub/ioarvanit/dual-axis-solar-tracker-panel-with-auto-and-manual-mode-41cfd9).

Code has already been optimized for arduino: https://pdfs.semanticscholar.org/ffd3/bb8b5e85c796da0ae3eac3be11117291289f.pdf

*****

Here is the next version of this design:

The thinking is to look around and find existing parts of medium to high quality in the lab, and design something which works around those preexisting parts. (I have the gears, the chain, the 3mm rod, and the ball bearings. The bearings we have don’t have 3mm inner diameter so right now they just turn around a hole in the 3D print / CNC milled axle holders. 

Here’s a right angle design with only one bearing and less hardware (there may be a weight distribution argument for one of these assemblies):

Remaking the gear (less improperly this time) with Sweep1 and scaled outline which I bent into a circle:

Here’s the model ready for print:

lazy explosion:

The 3D printed parts:

The begining of the bearing assembly:

The alignment was impossible to get right here:

 

 I ended up hacking together something with Paolo’s bearing and some old prints. After some sanding and forcing of parts together, here is the prototype:

 

Errata: 

-ball bearing spacing not great enough.The bearing did not fit together, I’m guessing because there wasn’t a big enough gap between the ball bearings and the two sides of the bearing.

-the upper bearing needs more depth in order to comfortably rest in place, but it just bearly works.

-the motor holders required many minutes of sanding and filing to fit the motors, but now it fits perfectly.

-the gear should probably be a miter, also there is nothing holding the sprocket down in place.

******

Took apart a bunch of small stuff to have small screws and rods:

To fix the board to the bar I used a part I found in a floppy disk drive:

 

Showing the M1.6 screws holding the top 3D print in place and some M3 black bolts to keep the inner bearing off the ground.

I wired up the two motors as well to see how that would work:

*******

Here is an attempt at making something similar from stepper motors (of course they need to be powered to hold their position so they can’t really be weight bearing). The nice thing about steppers is the mini linear threaded drives which could be added to the pan-tilt to give the machine the ability to move around shadows? 

 

3D modeling the pan tilt with two steppers:

…and one stepper / one DC gearmotor:

Here is the design worked a bit more and ready to print:

Here is how the print and assembly turned out:

 

I like how the translucent print blends with the different metal and plastic shades. For the electronics I’m planning four LRDs and a super simple program (with batt for super reactive demo?). One could either imagine a whole array of the same sun tracking devices, or a series of different families of devices mixed together in an array, which would all react in the same way to moving a light bulb into the space above the robots….

Errata:

-Everything is still a bit too snug with 0.1mm offsets. I should have made the spacing for the rail even bigger because it needs to actually slide…

-I designed using a bearing I only have one of and was already using in another machine…

-The holes for the read DC motor mounting didn’t come through.

-The top part which holds the rod and attaches to the linear rail broke because it was super weak in the middle.

-The bottom brace is not long enough to force the panel into more acute angles.

-The tension in the rubber belt is not sufficient to turn the base…

-The threaded rod nut plastic piece is not pushed sufficiently into the threaded rod to grip effectively. It needs to be closer to the rod so the built-in spring is in tension.

****************

I have some new parts: M2 bolts and nuts as well as steppers with gear reductions.

Taking apart more DVD roms I had the idea of remaking this device entirely from e-waste parts. I have six kits so far:

The idea would be to make this design:

There are about four sets of the same components available from the 8 DVD drives I took apart. I am redesigning the 3D model with these parts in mind.

There is also the possibility of using the motor drivers from the boards themselves except that they require a 12V VCC…

Here is a post describing how they could be hacked: https://electronics.stackexchange.com/questions/341519/i-need-help-controlling-the-sled-motor-of-a-cd-rom-based-off-of-a-datasheet

Image of the BD7907FS Circuit Diagram

Here are some details about this next design:

-it incorporates another found motor of the DVD rom device instead of the geared DC motor ordered from Polulu. 

-it has tracks instead of holes for sensitive spots (like the DC motor mount and the threaded rod nut) so that things can be adjusted and then bolted when they are just perfect.

-I replaced the central bearing for the correct diameter.

-I made the upper 3D printed peice more structurally sound so hopefully it won’t break this time. 

-I made larger offsets for inserts (except for the rod holders which I want to be snug) 0.2mm all around instead of 0.1mm this time. 

-I made a recessed track for the gear belt holder on the DC motor. 

-I fiddled such that the angle range for the panel is greater now. 

 

In parallel I’m working on the simplest version of a test board possible:

-super cap will need to be manually charged

-4 photodiodes for solar orientation will be manually wired to avoid challenging trace designs.

-only the most essential stuff for the motor drivers and microchip. 

The idea is that I can make a video showing the device tracking a light source in real time super “responsively”. This could then easily be modified to be the actual sun seeking circuit. 

I will have four little directional shaders which will cast shadows if the four photodiodes are not all pointed directly at the same light source. 

https://www.sciencedirect.com/science/article/abs/pii/S2213138818300080

Open hardware/software test bench for solar tracker with virtual instrumentation - ScienceDirect

I made a quick PCB then decided what I really need is an air wired arduino with motor drivers to test this.

Errata from second stepper prototype:

-The 3D printed piece that holds the leadscrew nut is too thick for my M2 bolts and so it cannot be bolted on.

-I forgot to subtract the bottom toothed part of the black gear belt wheel from the base.

-most of the offsets are too loose. 

-with the wider heavier DC motor the base is no longer stable enough.

-I forgot to subtract the flange of the DC motor (like a collar around the axle) from the bracket that it attached to.

Next I will get a quick mock up with some light sensors mounted on the four corners of the solar panel enabling an arduino to follow a light source. This won’t be embedded on a board yet, it will just be a test.

 

***********

I’m using a DRV8835 motor shield and an easy stepper motor driver for this mock up with the LDRs wired like this (but with 1Ks instead of 10Ks):

Working with Light Dependent Resistor (LDR) - Arduino Project Hub

Here is the code I’m using to control the LDR sensing sun seeker;

#include <DRV8835MotorShield.h>

#define LED_PIN 13

DRV8835MotorShield motors;

//Declare pin functions on Redboard
#define stp 2
#define dir 3
#define MS1 4
#define MS2 5

#define BPHASE 10
#define BEN 9

#define EN 6

int sensorPin1 = A0;
int sensorPin2 = A1;
int sensorPin3 = A2;
int sensorPin4 = A3;
int sensorValue1 = 0;
int sensorValue2 = 0;
int sensorValue3 = 0;
int sensorValue4 = 0;

//Declare variables for functions
char user_input;
int x;
int y;
int state;

void setup() {

Serial.begin(9600);
pinMode(sensorPin1, INPUT);
pinMode(sensorPin2, INPUT);
pinMode(sensorPin3, INPUT);
pinMode(sensorPin4, INPUT);

pinMode(stp, OUTPUT);
pinMode(dir, OUTPUT);
pinMode(MS1, OUTPUT);
pinMode(MS2, OUTPUT);
pinMode(EN, OUTPUT);
resetEDPins(); //Set step, direction, microstep and enable pins to default states

pinMode(LED_PIN, OUTPUT);

pinMode(BPHASE, OUTPUT);
pinMode(BEN, OUTPUT);
}

//Main loop
void loop() {

sensorValue1 = (analogRead(sensorPin1) + analogRead(sensorPin1) + analogRead(sensorPin1))/3;
sensorValue2 = (analogRead(sensorPin2) + analogRead(sensorPin2) + analogRead(sensorPin2))/3;

sensorValue3 = (analogRead(sensorPin3) + analogRead(sensorPin3) + analogRead(sensorPin3))/3;
sensorValue4 = (analogRead(sensorPin4) + analogRead(sensorPin4) + analogRead(sensorPin4))/3;

if(sensorValue1 > 500 && sensorValue1 > sensorValue2)
{
StepForwardDefault();
}

if(sensorValue2 > 500 && sensorValue2 > sensorValue1)
{
ReverseStepDefault();
}

if(sensorValue3 > 500 && sensorValue3 > sensorValue4)
{
forward(10);
nomove();

}

if(sensorValue4 > 500 && sensorValue4 > sensorValue3)
{
backward(10);
nomove();

}

//StepForwardDefault();
//ReverseStepDefault();

//forward(50);
//backward(50);
//nomove();

}

void forward(int t)
{

digitalWrite(BEN, HIGH); //forward
digitalWrite(BPHASE, LOW);
delay(t);

}

void backward(int t)
{

digitalWrite(BEN, HIGH); //backward
digitalWrite(BPHASE, HIGH);
delay(t);

}

void nomove()
{

digitalWrite(BEN, LOW); //no movement
digitalWrite(BPHASE, LOW);

}

//Reset Easy Driver pins to default states
void resetEDPins()
{
digitalWrite(stp, LOW);
digitalWrite(dir, LOW);
digitalWrite(MS1, LOW);
digitalWrite(MS2, LOW);
digitalWrite(EN, HIGH);
}

//Default microstep mode function
void StepForwardDefault()
{

digitalWrite(dir, LOW); //Pull direction pin low to move “forward”
for(x= 0; x<100; x++) //Loop the forward stepping enough times for motion to be visible
{
digitalWrite(stp,HIGH); //Trigger one step forward
delay(1);
digitalWrite(stp,LOW); //Pull step pin low so it can be triggered again
delay(1);
}

}

//Reverse default microstep mode function
void ReverseStepDefault()
{

digitalWrite(dir, HIGH); //Pull direction pin high to move in “reverse”
for(x= 0; x<100; x++) //Loop the stepping enough times for motion to be visible
{
digitalWrite(stp,HIGH); //Trigger one step
delay(1);
digitalWrite(stp,LOW); //Pull step pin low so it can be triggered again
delay(1);
}

}

// 1/8th microstep foward mode function
void SmallStepMode()
{

digitalWrite(dir, LOW); //Pull direction pin low to move “forward”
digitalWrite(MS1, HIGH); //Pull MS1, and MS2 high to set logic to 1/8th microstep resolution
digitalWrite(MS2, HIGH);
for(x= 0; x<1000; x++) //Loop the forward stepping enough times for motion to be visible
{
digitalWrite(stp,HIGH); //Trigger one step forward
delay(1);
digitalWrite(stp,LOW); //Pull step pin low so it can be triggered again
delay(1);
}

}

//Forward/reverse stepping function
void ForwardBackwardStep()
{

for(x= 1; x<5; x++) //Loop the forward stepping enough times for motion to be visible
{
//Read direction pin state and change it
state=digitalRead(dir);
if(state == HIGH)
{
digitalWrite(dir, LOW);
}
else if(state ==LOW)
{
digitalWrite(dir,HIGH);
}

for(y=0; y<1000; y++)
{
digitalWrite(stp,HIGH); //Trigger one step
delay(1);
digitalWrite(stp,LOW); //Pull step pin low so it can be triggered again
delay(1);
}
}

}

 

***********************

To make an on-board version of the breadboard prototype I made, I think I can reuse a previous version of this circuit which has two motor drivers and even a couple of spots for LDRs (I would just ignore the radio and sensor side of things for the moment at least):

(I may need to add a CS pull-up resistor and a 0.1uF cap to power as these were two erratta from this version of the board.) 

This turned out to be a bad idea, there are approximately 3,590 jumpers between the two boards, so no practical at all.

I am thinking of making miniature smd light sensor pairs (we have smd photodiodes in the lab) that would attach to the outside of the board on 3D printed T-shaped things:

When light is straight ahead, difference between LDRs will be minimal. Moment that one is significantly darker than the other, the motor which turns the dark side towards the light needs to come on until they are equalized again. So more of a nested if loop?

if(sensor1-sensor2 > 200){// difference in sensors

if(sensor1>100&&sensor2<50) //turn motor CW

else()//turn motor CCW

****************

Because the board already has the radio built in, I wonder if I should reincorperate it into the project. I also recieved some female SMA board antenna connectors which I could incorperate into the new version.

10Pcs SMA Female Solder Edge PCB Mount Straight RF Connector Plug ...

************

New code:

#include <Stepper.h>

// change this to the number of steps on your motor
#define STEPS 200

// create an instance of the stepper class, specifying
// the number of steps of the motor and the pins it’s
// attached to
Stepper stepper(STEPS, A2, A3, A5, A4);

#define RED 3 // RED LED

int sensorPin1 = A0;
int sensorPin2 = A1;
int sensorPin3 = A6;
int sensorPin4 = A7;
int sensorValue1 = 0;
int sensorValue2 = 0;
int sensorValue3 = 0;
int sensorValue4 = 0;

void setup()
{

pinMode(sensorPin1, INPUT);
pinMode(sensorPin2, INPUT);
pinMode(sensorPin3, INPUT);
pinMode(sensorPin4, INPUT);

pinMode(6, OUTPUT); //

pinMode(7, OUTPUT); //

// set the speed of the motor to 30 RPMs
stepper.setSpeed(60);
}

void loop()
{

digitalWrite(6, LOW); //
digitalWrite(7, LOW); //

sensorValue1 = (analogRead(sensorPin1) + analogRead(sensorPin1) + analogRead(sensorPin1))/3;
sensorValue2 = (analogRead(sensorPin2) + analogRead(sensorPin2) + analogRead(sensorPin2))/3;

sensorValue3 = (analogRead(sensorPin3) + analogRead(sensorPin3) + analogRead(sensorPin3))/3;
sensorValue4 = (analogRead(sensorPin4) + analogRead(sensorPin4) + analogRead(sensorPin4))/3;

if(sensorValue1 > 500 && sensorValue1 > sensorValue2)
{
clockwise();
delay(500);
}

if(sensorValue2 > 500 && sensorValue2 > sensorValue1)
{

counter_clockwise();
delay(500);
}

if(sensorValue3 > 500 && sensorValue3 > sensorValue4)
{
stepper.step(STEPS);

}

if(sensorValue4 > 500 && sensorValue4 > sensorValue3)
{
stepper.step(-STEPS);
}

digitalWrite(6, LOW); //
digitalWrite(7, LOW); //

}

int clockwise()
{

digitalWrite(6, HIGH); //
digitalWrite(7, LOW); //

}

int counter_clockwise()
{

digitalWrite(6, LOW); //
digitalWrite(7, HIGH); //

}

Circuit Protection + PCB Design Rules of Thumb

I just destroyed a circuit I spent over a week preparing and I decided I would learn how to better protect my circuits.

Reverse Polarity protection:

A diode can be used to protect a circuit but it will drop 0.7V and will waste power. A shotky diode will only drop .3-.4V but it has the same issue. A P-Channel MOSFET set up where the gate is connected to ground will only turn on when the polarity is correct. If Vin is not greater than the maximum allowed voltage you can put accross the MOSFET from gate to source (Vgs max.), or the Vin is not less than the threshold required for the P-FET to turn on (Vgs th), then it doesn’t need any other components.

Image result for how to protect circuits from reverse voltage polarity

For overvoltage protection (https://circuitdigest.com/electronic-circuits/overvoltage-protection-circuit):

When the voltage is below the Zener Diode’s 5.1V reverse threshold, Q2’s base is HIGH  (through the 2.2K resistor) so the PNP is off. This means that Q1 is ON (because it’s PNP base is connected to ground via 6.8K) and the circuit is powered.

When the voltage is above the Zener Diode’s 5.1V reverse threshold, Q2 is connected to ground and is turned on. This connects Q1 with VCC and therefore turns it off, disconnecting the circuit from the power. 

Overvoltage Protection Circuit Diagram

For short circuit protection:

Q2 is a PNP, Q1 is an NPN. Here is my understanding based on the site https://circuitdigest.com/electronic-circuits/short-circuit-protection-circuit-diagram

First a small amount of current reaches the base of Q1 (via R5 and the D2), causing it to turn on Q2. Now current flows through Q2 into R4 and D1 while keeping Q1 on. Current is no longer flowing through D2.

When a short occurs, current passes directly towards ground from Q2 and therefore no longer turns Q1 on. This turns off Q2 and now current passes via R5 and D2, skipping D1 and still skipping R2 towards Q1, directly to ground. Instead of having a short, we now have current passing through R5 and D2. 

Short Circuit Protection Block Diagram

PCB Design (from https://www.youtube.com/watch?time_continue=5&v=NJKZZArjdg8&feature=emb_logo):

-rounded corner for logic levels, straight corners “round edges”. (Though not everyone seems to agree on this). 45 degree angles are good, 90 are bad.

-minimize trace lengths, components electronically close should be physically close too. Longer traces have higher resistance, capacitance and inductance. 

-Think in terms of a signal chain, with input on the left moving towards output on the right. Divide things into building blocks. Build each block separately and then throw it on the main board. 

-VCC should be connected via a star-like formation to sub systems, with branches of equal length, NOT in a cascaded or serial way where the last sub system is furthest away from VCC. This will make the later sub systems vulnerable to noise produced by the upstream ones.

-Mechanical parts (pots, switches, barrel connectors) fail before electrical parts.

-watch out for your ground returns (the path that a component’s ground path with take to make it back to the power regulator). If it is zig zaggy and not short this is not ideal.

-don’t forget to add test points! 

This website helps to calculate the correct width of traces for a given current:

http://circuitcalculator.com/wordpress/2006/01/31/pcb-trace-width-calculator/

This resource looks good for more in depth: http://alternatezone.com/electronics/files/PCBDesignTutorialRevA.pdf

Here is a table showing minimum trace widths for different thicknesses of copper:

•••••••••••••••

-work in mils, most components are designed with 100 mil spacing (0.1″). 

-For your Eagle grid, had a 25 thou alt grid with a 50 thou main grid. Or a 25mil/10mil for finer work. Use a SNAP grid.

-bigger traces are better generally, they have lower DC resistance and lower inductance.

-25 thou for signal traces, 50 thou for power, 10-15 for traces going in between ICs is a good place to start. 

-oval shaped pads for ICs, circular for leaded resistors and caps. 

-minimize the number of drill bits that will be required by the board house to make your circuit.

-check that when you actually add the components, screws, etc., it all fits and doesn’t cause potential shorts. 

-do not mix analog and digital sub systems in the same circuit, nor high current or frequency and low current and frequency. 

-leave a rectangle at the top of the solder mask so you can write something in pen on the board!

-for a two sided board, the bottom can be a ground plane. You should not have the ground plane extend all the way to the edge of the board. The more copper in your ground path the lower the impedance. 

-Use multiple vias to connect the same signal to ground to lower impedance. 

-One bypass cap per IC: 10nF or 1nF for higher frequencies, and 1uF or 10uF for low frequencies

-boards are typically made with 1oz. copper thickness and are 1.6mm thick fiberglass FR4.

-don’t forget to add a signature/logo to your board!

Visualizing your circuit before building:

https://www.falstad.com/circuit/

Fab 15 Part VI

Here is my first attempt at making a video of this all working:

I would like the next version of the video to show:-starting charging from zero.-the burst of packets sent at the begining and how it finds a balance afterwards. 
 -the sky in the background so it’s easy to understand how the clouds effect the charging rate.Here is me assembling the final boards:

 

I tried to power the motors using the motor driver on the flip side, I got weird results until I unplugged the ICSP header. After that everything worked as expected except when the power supply was turned off for some reason the motor drivers stopped working.

I have a problem of not having enough pins broken out.

For the VEML7700, I downloaded the following Adafruit libraries:

https://github.com/adafruit/Adafruit_VEML7700

https://github.com/adafruit/Adafruit_BusIO

For some reason I also needed to include the SPI.h file otherwise it would not compile.

Adding the VEML7700 code somehow makes the original code no longer work… I should now try with a vanilla arduino just to make sure the test code works.

The VOUT voltage sensing appears to work. This is a nice option because it means that just by taking the integral of the VOUT we can see if the solar panel position is getting more light (i.e. no need for multiple light sensors if we’re willing to spend some energy on motors in the spirit of trail and error sensing).

I have noticed that LDO is not stable at 2.2V but dips to below 2V. I’m not sure how related this is to the power supply being connected to the LTC3105.

I am working on a new minimal iteration of the sun seeking functionality.

Here is another 3D model I’m working on. The idea is that it cannot destroy itself by accident (it can turn all the way around in both axes and not break anything). It is also independent of whatever surface it is placed on. The bearing at the center allows everything to rotate freely.

Here are some sketches of me trying to figure out how to model the rotary thing:

The resin prints were pretty disastrous… The bearing didn’t fit and neither did the motors or the central axis pin! After some filing and hot gluing things fit a bit better.

P1000330

Here is the full assembly. It’s extremely inelegant. Here are some issues:

-stiff wires.

-the weight of things…Everything is straining the central axis pin, and the main mast supporting the solar panel board is not being held straight up.

-The tilt arm is hitting the rotary gear, it needs to be smaller. 

-everything is incredibly fragile and finicky.

 

Replacing the mast with just a simple arm is less inelegant:

Of course now the machine can destroy itself by just turning into the board hits something…It also needs a better solution for the solar panel being attached to the board somehow that can be easily removed for programming. 

The main axis which fits into the bearing is still problematic. 

This beautiful object was made by Mr. Paulo Salvagione at Pier 9. This would make a better base for the rotating part of this project I think. It could be made so that it fits the motor very snugly with no play.

I’ve decided to make my life easier and to go towards a more obvious solution for the next iteration. It will at least give me a chance to see how the balance of the object behaves over the course of a day. I’ve printed this version before in PLA but never in resin.

I’m taking the offset of .1mm all around to make the motors fit snugly. 

Here is the Arduino code I have developed so far:

/*

*/

const int pgood = 3;
const int cap_voltage = A2;
const int delay_time = 100;
const int motor_time = 500;

float cap_reading_0;
float cap_reading_1;
float cap_reading_2;
float cap_reading_3;
float cap_reading_4;

float cap_reading_average;

int integral_0;
int integral_1;
int integral_2;
int integral_3;
int integral_4;

int integral_total;

int current_reading;
int last_reading;

// the setup function runs once when you press reset or power the board
void setup() {

// motor driver pins
pinMode(A4, OUTPUT);
pinMode(A5, OUTPUT);

pinMode(A0, OUTPUT);
pinMode(7, OUTPUT);

pinMode(cap_voltage, INPUT); //
pinMode(pgood, INPUT); //
}

// the loop function runs over and over again forever
void loop()
{
if (pgood==HIGH)
{
evaluate_east_west();
evaluate_north_south();
}
}
int evaluate_east_west()
{
last_reading = integral();
clockwise();
delay(motor_time);
current_reading = integral();

if(last_reading>current_reading) // move back if less sun in new position
{
counter_clockwise();
delay(motor_time);
}

last_reading = integral();
counter_clockwise();
delay(motor_time);
current_reading = integral();

if(last_reading>current_reading) // move back if less sun in new position
{
clockwise();
delay(motor_time);
}
}

int evaluate_north_south()
{
last_reading = integral();
tilt_up();
delay(motor_time);
current_reading = integral();

if(last_reading>current_reading) // move back if less sun in new position
{
tilt_down();
delay(motor_time);
}

last_reading = integral();
tilt_down();
delay(motor_time);
current_reading = integral();

if(last_reading>current_reading) // move back if less sun in new position
{
tilt_up();
delay(motor_time);
}
}

int cap_voltage_read()
{
cap_reading_0 = analogRead(cap_voltage);
delay(delay_time);
cap_reading_1 = analogRead(cap_voltage);
delay(delay_time);
cap_reading_2 = analogRead(cap_voltage);
delay(delay_time);
cap_reading_3 = analogRead(cap_voltage);
delay(delay_time);
cap_reading_4 = analogRead(cap_voltage);
delay(delay_time);

return cap_reading_average = (cap_reading_0 + cap_reading_1 + cap_reading_2 + cap_reading_3 + cap_reading_4) / 5;
}

int integral()
{

integral_0 = (int)cap_voltage_read(); // convert to int
delay(delay_time);
integral_1 = (int)cap_voltage_read(); // convert to int
delay(delay_time);
integral_2 = (int)cap_voltage_read(); // convert to int
delay(delay_time);
integral_3 = (int)cap_voltage_read(); // convert to int
delay(delay_time);
integral_4 = (int)cap_voltage_read(); // convert to int
delay(delay_time);

return integral_total = integral_0 + integral_1 + integral_2 + integral_3 + integral_4;
}

int clockwise()
{
digitalWrite(A5, HIGH); //
digitalWrite(A4, LOW); //

digitalWrite(A0, LOW); //
digitalWrite(7, LOW); //
}

int counter_clockwise()
{
digitalWrite(A5, LOW); //
digitalWrite(A4, HIGH); //

digitalWrite(A0, LOW); //
digitalWrite(7, LOW); //
}

int tilt_up()
{
digitalWrite(A5, LOW); //
digitalWrite(A4, LOW); //

digitalWrite(A0, HIGH); //
digitalWrite(7, LOW); //
}

int tilt_down()
{
digitalWrite(A5, LOW); //
digitalWrite(A4, LOW); //

digitalWrite(A0, LOW); //
digitalWrite(7, HIGH); //
}

 

The current issue I’m having is with PGOOD which is for some reason hovering around 1V instead of 2.2V. When I remove the PGOOD test things appear to work.

Here is the resin print, it’s not bad! I think I will turn the top arm outwards so that no matter what happens the machine won’t destroy itself (at least during the testing phase).

And here is with the board attached:

And here is a video of the thing rotating:

P1000390

PGOOD is not working so I’m just making the code test the voltage of the capacitor when it wakes up. I’ve also added a motor_stop() function because I forgot to stop the motors turning during the time consuming voltage checking functions. This appears to work.

void loop()
{
if(((int)cap_voltage_read()) > 410)

// this is 1/3 – 20K/10K R divider of 2.7V out of a 2.2V LDO scale, mapped into 1023
{
evaluate_east_west();
evaluate_north_south();
}
}

I was noticing that there was considerable leakage from the capacitor without serious sun. I decided this was probably from having the motor driver sleep pin connected to PGOOD. I have disconnected PGOOD from the micro-controller, and now used that pin to turn on and off the motor sleep. If this doesn’t solve the problem the other candidate is the leakage from the resistor divider which could be replaced by a mosfet as per the JeeLabs zero current measuring post. This would require another pin from the microchip and a bit more space on my already crammed board…

(The next version of this board may need to be manufactured at a board house, not being able to easily make two sided boards is becoming very frustrating. I also want to use the fancy RF connectors and antennae I ordered.)

Hunting for the cause of the leaking current. The voltage seems to stabilize at 1.29V, not sure what that tells us though..

I’m using our super fancy Keithley DMM7510 7 1/2 Digit Multimeter. Check it out:

I added sleep mode to the code and now once the voltage hits 2.6V it stays essentially stable. (The motor driver uses 1.6-2.5uA @ 5V, the atmega 328p 1uA @ 3V, and the 3V/30K voltage divider draws 100uA.)

Already mentioned blog posts from Jeelabs on measuring battery voltage:

https://jeelabs.org/2013/05/15/what-if-we-want-to-know-the-battery-state/

https://jeelabs.org/2013/05/16/measuring-the-battery-without-draining-it/

https://jeelabs.org/2013/05/17/zero-powe-battery-measurement/

I’m wondering if I want to make things easier and have four mini solar panels and two comparators like this (http://www.ti.com/lit/ds/sbos589/sbos589.pdf) so that only two pins are required to determine which direction to move in. I could also possibly use the BEAM solarbotics “suspended bicore” solution (http://www.beam-online.com/Robots/Circuits/circuits.html#Phototropic%20Bicore).

There is a flaw in my system, if suddenly the sun comes out at the perfect time, the robot can think that turning away from the sun led to finding more sun whereas in fact it was just the sun that changed. I could solve this by having the robot do multiple experiments before committing to actually changing its angle. 

I should also include in the code a moment where the machine decides if the difference between the past and current reading is sufficiently great to necessitate moving. 

I have another problem. There is some give in the gearmotors, therefore they do not turn the same amount when they switch directions. This is bad but it’s critical when combined with the code not working very well. This is more an issue for the tilt motor, so if I could replace this with an earlier design rotating a metal rod and using a mast to take the weight of the board perhaps that would solve my problem. 

I’m hoping I wouldn’t need these: https://www.pololu.com/product/4761…

Just realized my code is not doing what I want it to do. The integral() function is absolute, it is adding bigger and bigger numbers instead of looking at the difference between relative values…Fixed this. 

I find the machine spends a lot of time moving back and forth between the same positions. It is rarely deciding that a new orientation is better than an old. I should get the radio set up so I can see the values that are being sent.

I also need to replace the tilt mechanism with one that holds the weight of the board like the mast/rotation system I tried earlier. I should also do east/west rotation before moving on to doing both axes at once.

Did a quick test, analogRead() has 10 bit resolution, giving a value between 0-1023. The resolution is barely good enough for taking a reading every 10 seconds and seeing a dropping voltage value in the cap. I think I should be taking measurements every few minutes to be able to detect a difference in charging. 

I think I need to turn the radio off for long delays, otherwise it doesn’t work. I’m trying radio.sleep(). 

I also realized it would make far more sense to sense the solar panel voltage rather than the capacitor voltage to sense the solar aspect. However this would add another input pin…

*I think I might need to update the below code to include the floor() function which stops arduino from rounding? https://www.nongnu.org/avr-libc/user-manual/group__avr__math.html#ga0f0bf9ac2651b80846a9d9d89bd4cb85

Here is the far from optimal code so far:

// Include the RFM69 and SPI libraries:
#include <SPI.h>
#include <avr/wdt.h>
#include <RFM69.h>
#include <avr/sleep.h>
#include “LowPower.h”

// Addresses for this node. CHANGE THESE FOR EACH NODE!

#define NETWORKID 0 // Must be the same for all nodes
#define MYNODEID 2 // My node ID
#define TONODEID 1 // Destination node ID

// RFM69 frequency, uncomment the frequency of your module:

//#define FREQUENCY RF69_433MHZ
#define FREQUENCY RF69_915MHZ

// AES encryption (or not):

#define ENCRYPTKEY “TOPSECRETPASSWRD” // Use the same 16-byte key on all nodes

// Use ACKnowledge when sending messages (or not):

#define USEACK true // Request ACKs or not

// Packet sent/received indicator LED (optional):

#define LED A3 // LED positive pin

#define PGOOD 3 // PGOOD

#define MOSFET 9//

// Create a library object for our RFM69HCW module:

const int cap_voltage = A2;
const int delay_time = 100; //30 x delay_time (?) is how long it takes to take an integral of cap voltage
const int long_delay_time = 7000; //30 x delay_time (?) is how long it takes to take an integral of cap voltage

double T;

const int motor_sleep = 3;
const int motor_time = 200;

int current_reading;
int last_reading;

RFM69 radio;

void setup()
{
// Open a serial port so we can send keystrokes to the module:

pinMode(LED,OUTPUT);
digitalWrite(LED,LOW);
pinMode(MOSFET,OUTPUT); //mosfet
// pinMode(PGOOD, INPUT); // PGOOD

// motor driver pins
pinMode(A4, OUTPUT);
pinMode(A5, OUTPUT);

pinMode(A0, OUTPUT);
pinMode(7, OUTPUT);

pinMode(motor_sleep, OUTPUT);
pinMode(cap_voltage, INPUT); //

}

void loop()
{

wdt_enable(WDTO_8S);

digitalWrite(MOSFET, LOW); // turn off MOSFET

if(((int)cap_voltage_read()) > 410)
{
digitalWrite(motor_sleep, LOW); // sleep motor driver
Radio_Send(); //includes init and mosfet turn on
digitalWrite(MOSFET, LOW); // turn off radio

T = integral();

Radio_Send();
digitalWrite(MOSFET, LOW); // turn off MOSFET
evaluate_east_west();
}
else
{
digitalWrite(motor_sleep, LOW); // sleep motor driver
digitalWrite(MOSFET, LOW); // turn off MOSFET
sleep(); // sleep microchip
}
}

int evaluate_east_west()
{
last_reading = integral();
wdt_reset(); // do this before 8 seconds has elapsed so we don’t reset
motors_off(); //also sleeps driver
wait_long();
wdt_reset(); // do this before 8 seconds has elapsed so we don’t reset
clockwise();
delay(motor_time);
motors_off();
current_reading = integral();
wdt_reset(); // do this before 8 seconds has elapsed so we don’t reset

if(last_reading>=current_reading) // move back if less sun in new position
{
counter_clockwise();
delay(motor_time);
motors_off();
}
wdt_reset(); // do this before 8 seconds has elapsed so we don’t reset

wait_long();

last_reading = integral();
wdt_reset(); // do this before 8 seconds has elapsed so we don’t reset
counter_clockwise();
delay(motor_time);
motors_off();
wdt_reset(); // do this before 8 seconds has elapsed so we don’t reset
delay(long_delay_time);
wdt_reset(); // do this before 8 seconds has elapsed so we don’t reset
current_reading = integral();
wdt_reset(); // do this before 8 seconds has elapsed so we don’t reset

if(last_reading>=current_reading) // move back if less sun in new position
{
clockwise();
delay(motor_time);
motors_off();
}
digitalWrite(motor_sleep, LOW);
}

int Radio_Send()
{
char Tstr[10];

digitalWrite(MOSFET, HIGH); // turn on MOSFET
delay(100);
radio.initialize(FREQUENCY, MYNODEID, NETWORKID);
radio.setHighPower(); // Always use this for RFM69HCW

// Turn on encryption if desired:

radio.encrypt(ENCRYPTKEY);

char buffer[50];

dtostrf(T, 5,5, Tstr);

static int sendlength = strlen(buffer);

sprintf(buffer, ” T:%s”, Tstr);

radio.sendWithRetry(TONODEID, buffer, sendlength);

Blink(LED,100);

}

int integral()
{
int integral_0;
int integral_1;

//int integral_total;

int integral_total_1;

integral_0 = (int)cap_voltage_read(); // convert to int
wdt_reset(); // do this before 8 seconds has elapsed so we don’t reset
wait_long();
wait_long();
wdt_reset(); // do this before 8 seconds has elapsed so we don’t reset
integral_1 = (int)cap_voltage_read(); // convert to int
wdt_reset(); // do this before 8 seconds has elapsed so we don’t reset

integral_total_1 = integral_1 – integral_0;

return integral_total_1;
}

int cap_voltage_read()
{
float cap_reading_0;
float cap_reading_1;
float cap_reading_2;
float cap_reading_3;
float cap_reading_4;

float cap_reading_average;

cap_reading_0 = analogRead(cap_voltage);
delay(delay_time);
cap_reading_1 = analogRead(cap_voltage);
delay(delay_time);
cap_reading_2 = analogRead(cap_voltage);
delay(delay_time);
cap_reading_3 = analogRead(cap_voltage);
delay(delay_time);
cap_reading_4 = analogRead(cap_voltage);
delay(delay_time);

return cap_reading_average = (cap_reading_0 + cap_reading_1 + cap_reading_2 + cap_reading_3 + cap_reading_4) / 5;
}

void Blink(byte PIN, int DELAY_MS)
// Blink an LED for a given number of ms
{
digitalWrite(PIN,HIGH);
delay(DELAY_MS);
digitalWrite(PIN,LOW);
}

void sleep(void)
{
digitalWrite(MOSFET, LOW); // turn on MOSFET
set_sleep_mode(SLEEP_MODE_PWR_DOWN); //select PWR DOWN, the most power savings
sleep_enable(); //set SE bit
sei(); // enable global interrupts
sleep_cpu(); //actually sleep
sleep_disable(); //code reaches this point after interrupt
}

int motors_off()
{
digitalWrite(motor_sleep, LOW); //put driver to sleep
digitalWrite(A5, LOW); //
digitalWrite(A4, LOW); //

digitalWrite(A0, LOW); //
digitalWrite(7, LOW); //
}

int clockwise()
{
digitalWrite(motor_sleep, HIGH); //wake up driver
digitalWrite(A5, HIGH); //
digitalWrite(A4, LOW); //

digitalWrite(A0, LOW); //
digitalWrite(7, LOW); //
}

int counter_clockwise()
{
digitalWrite(motor_sleep, HIGH); //wake up driver
digitalWrite(A5, LOW); //
digitalWrite(A4, HIGH); //

digitalWrite(A0, LOW); //
digitalWrite(7, LOW); //
}

int tilt_up()
{
digitalWrite(motor_sleep, HIGH); //wake up driver
digitalWrite(A5, LOW); //
digitalWrite(A4, LOW); //

digitalWrite(A0, HIGH); //
digitalWrite(7, LOW); //
}

int tilt_down()
{
digitalWrite(motor_sleep, HIGH); //wake up driver
digitalWrite(A5, LOW); //
digitalWrite(A4, LOW); //

digitalWrite(A0, LOW); //
digitalWrite(7, HIGH); //
}

int wait_long()
{

for(int i=0;i<10;i++)
{
wdt_reset(); // do this before 8 seconds has elapsed so we don’t reset
digitalWrite(motor_sleep, LOW); //put driver to sleep
digitalWrite(MOSFET, LOW); // turn off radio MOSFET
LowPower.idle(SLEEP_4S, ADC_OFF, TIMER2_OFF, TIMER1_OFF, TIMER0_OFF,
SPI_OFF, USART0_OFF, TWI_OFF);
}

}

DIY Mini Drone

For a change, this is a video of me working on the boards for this project:

 

 

Radios are working, I’m struggling with the best way to poll the joysticks. I think I need to use Pin Change Interrupts (Interrupts for pins other than those dedicated for interrupting). The other option is just to have polling:

if (UP == HIGH){ Send(UP);}

if (DOWN == HIGH){ Send(DOWN);}

etc.

*Later realized that I messed this up, what I want is to check if the pin is LOW (i.e. if it is connected to ground and not internally pulled up) and then have an else at the end which turns to HIGH.

*I forgot to put pull-up resistors on the actual board so I used the avr’s internal ones. In arduino you do this like so:

pinMode(A0, INPUT_PULLUP);

I reprinted the drone frame with .1mm extra space around the circle and now the motors fit snuggly. 

Dissapointed that the joysticks only register an up or down when also pushed down…

Here is the joystick sending code:

********************************************************************************

// RFM69HCW Example Sketch
// Send serial input characters from one RFM69 node to another
// Based on RFM69 library sample code by Felix Rusu
// http://LowPowerLab.com/contact
// Modified for RFM69HCW by Mike Grusin, 4/16

// This sketch will show you the basics of using an
// RFM69HCW radio module. SparkFun’s part numbers are:
// 915MHz: https://www.sparkfun.com/products/12775
// 434MHz: https://www.sparkfun.com/products/12823

// See the hook-up guide for wiring instructions:
// https://learn.sparkfun.com/tutorials/rfm69hcw-hookup-guide

// Uses the RFM69 library by Felix Rusu, LowPowerLab.com
// Original library: https://www.github.com/lowpowerlab/rfm69
// SparkFun repository: https://github.com/sparkfun/RFM69HCW_Breakout

// Include the RFM69 and SPI libraries:

#include <RFM69.h>
#include <SPI.h>

// Addresses for this node. CHANGE THESE FOR EACH NODE!

#define NETWORKID 0 // Must be the same for all nodes (0 to 255)
#define MYNODEID 1 // My node ID (0 to 255)
#define TONODEID 2 // Destination node ID (0 to 254, 255 = broadcast)

// RFM69 frequency, uncomment the frequency of your module:

//#define FREQUENCY RF69_433MHZ
#define FREQUENCY RF69_915MHZ

// AES encryption (or not):

#define ENCRYPT true // Set to “true” to use encryption
#define ENCRYPTKEY “TOPSECRETPASSWRD” // Use the same 16-byte key on all nodes

// Use ACKnowledge when sending messages (or not):

#define USEACK true // Request ACKs or not

// joystick and leds

#define LED1 A0 // LED positive pin
#define UP1 A2//
#define LEFT1 A3//
#define RIGHT1 A4//
#define DOWN1 A5//

#define LED2 A1 // LED positive pin
#define UP2 8//
#define LEFT2 9//
#define RIGHT2 7//
#define DOWN2 6//

// Create a library object for our RFM69HCW module:
RFM69 radio;

void setup()
{
// leds and joystick init

pinMode(LED1,OUTPUT);
pinMode(LED2,OUTPUT);

pinMode(UP1,INPUT_PULLUP);
pinMode(LEFT1,INPUT_PULLUP);
pinMode(RIGHT1,INPUT_PULLUP);
pinMode(DOWN1,INPUT_PULLUP);

pinMode(UP2,INPUT_PULLUP);
pinMode(LEFT2,INPUT_PULLUP);
pinMode(RIGHT2,INPUT_PULLUP);
pinMode(DOWN2,INPUT_PULLUP);

// Initialize the RFM69HCW:

radio.initialize(FREQUENCY, MYNODEID, NETWORKID);
radio.setHighPower(); // Always use this for RFM69HCW

// Turn on encryption if desired:

if (ENCRYPT)
radio.encrypt(ENCRYPTKEY);
}

void loop()
{
//setting up variables for button states

int sensorVal0 = digitalRead(UP1);
int sensorVal1 = digitalRead(LEFT1);
int sensorVal2 = digitalRead(RIGHT1);
int sensorVal3 = digitalRead(DOWN1);
int sensorVal4 = digitalRead(UP2);
int sensorVal5 = digitalRead(LEFT2);
int sensorVal6 = digitalRead(RIGHT2);
int sensorVal7 = digitalRead(DOWN2);

// SENDING

// In this section, we’ll gather serial characters and
// send them to the other node if we (1) get a carriage return,
// or (2) the buffer is full (61 characters).

// If there is any serial input, add it to the buffer:

char buffer[5] = “z”;

//BUTTON READING AND SENDING

if (sensorVal0 == LOW) {
buffer[0] = ‘a’;
digitalWrite(LED2, HIGH);
}

else if (sensorVal1 == LOW) {
buffer[0] = ‘b’;
digitalWrite(LED2, HIGH);
}

else if (sensorVal2 == LOW) {
buffer[0] = ‘c’;
digitalWrite(LED2, HIGH);
}

else if (sensorVal3 == LOW) {
buffer[0] = ‘d’;
digitalWrite(LED2, HIGH);
}

else if (sensorVal4 == LOW) {
buffer[0] = ‘e’;
digitalWrite(LED1, HIGH);
}

else if (sensorVal5 == LOW) {
buffer[0] = ‘f’;
digitalWrite(LED1, HIGH);
}

else if (sensorVal6 == LOW) {
buffer[0] = ‘g’;
digitalWrite(LED1, HIGH);
}

else if (sensorVal7 == LOW) {
buffer[0] = ‘h’;
digitalWrite(LED1, HIGH);
}

else {
buffer[0] = ‘z’;
digitalWrite(LED2, LOW);
digitalWrite(LED1, LOW);
}

// END OF BUTTON STUFF

if(buffer[0]!=’z’)
{

static int sendlength = 3;

radio.sendWithRetry(TONODEID, buffer, sendlength);
}

}

********************************************************************************

 

And here is the receiver code:

 

*********************************************************************************

// RFM69HCW Example Sketch
// Send serial input characters from one RFM69 node to another
// Based on RFM69 library sample code by Felix Rusu
// http://LowPowerLab.com/contact
// Modified for RFM69HCW by Mike Grusin, 4/16

// This sketch will show you the basics of using an
// RFM69HCW radio module. SparkFun’s part numbers are:
// 915MHz: https://www.sparkfun.com/products/12775
// 434MHz: https://www.sparkfun.com/products/12823

// See the hook-up guide for wiring instructions:
// https://learn.sparkfun.com/tutorials/rfm69hcw-hookup-guide

// Uses the RFM69 library by Felix Rusu, LowPowerLab.com
// Original library: https://www.github.com/lowpowerlab/rfm69
// SparkFun repository: https://github.com/sparkfun/RFM69HCW_Breakout

// Include the RFM69 and SPI libraries:

#include <SPI.h>
#include <RFM69.h>

// Addresses for this node. CHANGE THESE FOR EACH NODE!

#define NETWORKID 0 // Must be the same for all nodes
#define MYNODEID 2 // My node ID
#define TONODEID 1 // Destination node ID

// RFM69 frequency, uncomment the frequency of your module:

//#define FREQUENCY RF69_433MHZ
#define FREQUENCY RF69_915MHZ

// AES encryption (or not):

#define ENCRYPT true // Set to “true” to use encryption
#define ENCRYPTKEY “TOPSECRETPASSWRD” // Use the same 16-byte key on all nodes

// Use ACKnowledge when sending messages (or not):

#define USEACK true // Request ACKs or not

// Packet sent/received indicator LED (optional):

#define LED 1 // LED positive pin

// Create a library object for our RFM69HCW module:

RFM69 radio;

void setup()
{
// Open a serial port so we can send keystrokes to the module:

pinMode(LED,OUTPUT);
digitalWrite(LED,LOW);

radio.initialize(FREQUENCY, MYNODEID, NETWORKID);
radio.setHighPower(); // Always use this for RFM69HCW

if (ENCRYPT)
radio.encrypt(ENCRYPTKEY);

}

void loop()
{

// RECEIVING

// In this section, we’ll check with the RFM69HCW to see
// if it has received any packets:

if (radio.receiveDone()) // Got one!
{
// Print out the information:

// The actual message is contained in the DATA array,
// and is DATALEN bytes in size:

// char message = radio.DATA[0];

// RSSI is the “Receive Signal Strength Indicator”,
// smaller numbers mean higher power.

// Send an ACK if requested.
// (You don’t need this code if you’re not using ACKs.)

if (radio.ACKRequested())
{
radio.sendACK();
}
Blink(LED,10);
}

}

void Blink(byte PIN, int DELAY_MS)
// Blink an LED for a given number of ms
{
digitalWrite(PIN,HIGH);
delay(DELAY_MS);
digitalWrite(PIN,LOW);
}

*********************************************************************************

 

Now just waiting for some new pager motors to arrive…

I’ve got some old drones which I have taken apart for batteries, motors and propellers. The motors are slightly larger to I have redesigned the 3D print. The motors are 8.5mm in diameter and I found that subtracting with an 8.8mm cylinder make for the snuggest fit.

Binary Visualizing

Using the tool bin vis, which simply assigns a shade of grey for each byte in a file, it’s possible to represent the structure of pieces of a file. Check it out, these are found 3D files from various software programs:

 

Found a cool surprise when I uploaded a .BMP file, the bytes map almost perfectly onto the image;

I want to try other uncompressed formats like RAW. Loading PNGs and JPEGs are uninteresting so far, they are just noise.

I have tried some experiments processing this data. These stem from the observation that changing the width of the viewing window, which causes the binary data to wrap around the screen, changes the representation of the data dramatically. 

In this experiment I tried to adjust the window of the binary visualizing screen to get the data to make columns, to the extend that this was possible. Some of this info must repeat at a point in the middle of a byte and therefore not map onto a grid of pixels perfectly (?).

Here is an attempt to isolate just the modules which repeat in the above image and to display only them;

I am imagining a program which goes through the file and figures out the proper width for each chunk of data so that this process can be automated. 

Some experiments I would like to try:

-what does the same form look like (say, a sphere) in different software formats?

-is it possible to identify which part of the binary file links up with which part of the 3D file? Could you isolate the repeating element and figure out exactly what it’s composed of?

-what are the similarities and differences between different 3D objects saved by the same software? (I.e. what is the software grain?)

-what do the Rhino.exe, Adobe Illustrator.exe and Revit.exe files look like?

-show a before and after compression image.

-somehow look at a program’s operation by examining it’s buffer memory live somehow?

and here’s the view of just the pixels in the same file just changing the window width:

Essentially each eight bits (eg. 01101001) are transformed into a pixel with a value of grey between black (0) and white (255):

I just visited the Glasgow Botanical Garden and watched the film Aquarela. Both experiences reminded me about the diversity of patterns and permutation of simple rules at play in the cosmos.

Image result for aquarela film"Image result for aquarela film"

Aquerela (2019) Screenshot

Image result for botanical garden glasgow"

Glasgow botanical gardens (image from http://martinbrookes.blogspot.com/2018/06/the-botanical-gardens-glasgow.html)

 

Looking at a Rhino file in a text editor you get that same “grain” feel as with bin vis:

this is from https://developer.rhino3d.com/api/RhinoCommon/html/N_Rhino_FileIO.htm

but there is also: https://developer.rhino3d.com/guides/#opennurbs

It would seem a lot easier to start with a file format that is ASCII encoded though…

This is a RAW file opened in binview, it has several images contained in it, one for each color channel I guess:

 

Here is a Bitmap file saved with interleave:

An IGS file format, ASCII readable, visualized. Pretty boring unfortunately.

I found a head inside an example Rhino file :D!

Some tests with a single image saved in different formats:

 

Sphere test:

Cube test:

Zooming in to some patterns:

Some patterns I found in 3D files (would be cool to compare to image file observations!):

With red to help identify the patterns:

For comparison here are some samples from image files:

Comparing an all white vs. all black file:

Next experiment is to copy and paste pieces of one file into others. Possibly from a compressed file into a raw file! (Wait – why?)

Insight into what we’re seeing in these files: http://www.rumint.org/gregconti/publications/taxonomy-bh.pdf

when things line up into a structure, data is fixed length. When things don’t line up we get variable length data chunks. Repeating values seem to help align data regions. Nois is encrypted in some way typically which has scrambled the structure. 

*****

The problem with this visualization is that it does not represent TIME, like my other ones. It would be cool to stretch and compress these images based on the speed with which the files were written somehow. 

**************

Update: This software called HeapMemory (https://www.nirsoft.net/utils/heap_memory_view.html) allows you to see memory created by active programs. You can output the data and then visualize it with binvis. If you did this regularly while you worked on a 3D model, you could have a representation of the file you’re working on through the eyes of the computer program. 

Here is a gif of a rhino operation and the change in the 3dm file:

and here’s a timelapse of a rhino file with transformations taking place:

UPSI Lecture Prep

 

To “present my projects or any other insights on digital fabrication, education and architecture.” The context; “The class is the second part of an intensive course on 3d modelling and CNC milling to make an 1:1 architectural structure based on simple modules.”

Here are some questions I could respond to: What are the seams, the gaps, and the moments of translation, between various subsystems in our contemporary digital design workflow?
How has software engineering culture given form to our software?
How does the computer internally represent our work – how does it “see” our design files and “understand” our design work?
Does software have a “grain”, just like wood and other materials? What is the ontology of Revit and what is the world according to Rhino 3D, for instance?
Do technological artifacts, and the objects that designers make, have innate force in themselves, as Bruno Latour and Jane Bennett seem to suggest?

I am planning a revised lecture from my UdK workshop. I would also like to present some new research but my compression research is not leading to a tangible visualization yet, I need to ask for help from programmers to accelerate this process perhaps. The other solution appears to be to go towards simpler technology from further back in history. This has the added bonus of me not working on visualizing something that a million other people are already working on as with image compression visualization. Taking a look at my map of gaps diagram…

I would like to make a GIF of the Revit startup elements. I also want to incorporate Schlossman lecture material like the number of software programs that used to exist that have all been eaten by Autodesk:

OMG here is the mother lode for all things memory visualization, this is incredibly impressive: https://reverseengineering.stackexchange.com/questions/6003/visualizing-elf-binaries

downloaded bin vis from this link, it has an .exe in the debug file: http://www.rumint.org/gregconti/publications/binviz_0.zip

I could use the techniques from the following video to compare Rhino to Revit live, or look at types of files that architects use. At the very least I could make a nice slide showing the “grain” of these different programs! I could also make the argument that because computers are so much faster than us, they can see more data at a time than we can and therefore it looks to them like watching an image (I could get the speed of their reading to equal the number of pixels we can see at a given time). 

Here is a lecture which outlines the method of mapping binary to pixel shades and how you can begin to identify species of data: https://www.youtube.com/watch?v=h68VS7lsNfE

keywords:

memory map, visual reverse engineering

https://reverseengineering.stackexchange.com/questions/6003/visualizing-elf-binaries:

word document:

Windows PE visualization

Documents Format Files

enter image description here

enter image description here

pdf:

http://actinid.org/vix/

http://binvis.io/

…I could look at things like scanners, or floppy disks?

 

In the illustration above, you can see how the disk is divided into tracks (brown) and sectors (yellow).

Floppy Disks are divided into tracks. 

Image result for kryoflux"

Nice images on how floppy disks can be damaged and the effect it has on the data https://goughlui.com/2013/04/21/project-kryoflux-part-3-recovery-in-practise/

magnetic field

speed variation

From https://link.springer.com/referenceworkentry/10.1007%2F0-387-23483-7_95 :

Data remanance:

  • Write heads used on exchangeable media (e.g., floppy disks, magstripe cards) differ slightly in position and width due to manufacturing tolerances. As a result, one writer might not overwrite the entire area on a medium that had previously been written to by a different device. Normal read heads will only give access to the most recently written data, but special high-resolution read techniques (e.g., magnetic-force microscopy) can give access to older data that remains visible near the track edges.

  • Even with a perfectly positioned write head, the hysteresis properties of ferromagnetic media can result in a weak form of previous data to remain recognizable in overwritten areas. This allows the partial recovery of..

Data is not written linearly ( 😛 ) but interleaved https://en.wikipedia.org/wiki/Interleaving_(disk_storage):

Information is commonly stored on disk storage in very small pieces referred to as sectors or blocks. These are arranged in concentric rings referred to as tracks across the surface of each disk. While it may seem easiest to order these blocks in direct serial order in each track, such as 1 2 3 4 5 6 7 8 9, for early computing devices this ordering was not practical.

[…]

To correct for the processing delays, the ideal interleave for this system would be 1:4, ordering the sectors like this: 1 8 6 4 2 9 7 5 3. It reads sector 1, processes for three sectors whereby 8 6 and 4 pass by, and just as the computer becomes ready again, sector two is arriving just as it is needed.

From the Scanning world:

scanners can interpolate pixels between scanned pixels and assume their value. This is done in software but also on chip.

Here are the proposed changes to the UdK presentation and my stock clickspace project presentation:

  1. I think I will first present my work, then talk a little about the materiality and social dimensions of technology afterwards. 

Since doing this workshop Hannah Perner-Wilson connected me with this article by Tim Ingold: https://journal.culanth.org/index.php/ca/article/view/ca30.4.03/200

I forgot to mention the materiality of how electricity is produced (by either wresting with the energy within matter itself, or burning compressed dinosaurs). Very interesting point about how electricity in modern industrial society becomes a controlling apparatus, closing itself off from people who become consumers sheltered from the actual infrastructure of electricity. When we use electricity we’re participating in a woven super structure which can help us move away from the concept of the object.

I should investigate more the Anthropocene, thunder and the electric chair along with the references in this article.

Second article The Textility of Making by Tim ingold he writes: “I want to argue that what Klee said of art is true of skilled practice in general, namely that it is a question not of imposing preconceived forms on inert matter but of intervening in the fields of force and currents of material wherein forms are generated. Practitioners, I contend, are wanderers, wayfarers, whose skill lies in their ability to find the grain of the world’s becoming and to follow its course while bending it to their evolving purpose”.

This seems to fit with the harnessing of electricity and, based on an understanding of it’s movement through various media and in various situations, co-creating something that works with this “grain”. It seems important to note that modern software has a “grain” too.

Since this workshop I have also became more interested in Legacy code (and if it could be possible to look at the varying ages of code in a big program somehow), code that needs to be ported or refactored from old code paradigmes into new ones. https://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052. So far what’s interesting here is the language used to describe “code rot”. Here are some samples: “the phrase strikes disgust in the hearts of programmers. It conjured images of slogging through a murky swamp of tangled undergrowth with leaches beneath and stinging flies above. It conjures odors of murk, slime, stagnancy and offal…tangled, opaque, convoluted system…” referred to collectively as “rot”. 

Wikipedia talks about the Big Ball of Mud: A big ball of mud is a software system that lacks a perceivable architecture. Although undesirable from a software engineering point of view, such systems are common in practice due to business pressures, developer turnover and code entropy.  

They link to Brian Foote’s article:

A Big Ball of Mud is a haphazardly structured, sprawling, sloppy, duct-tape-and-baling-wire, spaghetti-code jungle. These systems show unmistakable signs of unregulated growth, and repeated, expedient repair. Information is shared promiscuously among distant elements of the system, often to the point where nearly all the important information becomes global or duplicated.

The overall structure of the system may never have been well defined.

If it was, it may have eroded beyond recognition. Programmers with a shred of architectural sensibility shun these quagmires. Only those who are unconcerned about architecture, and, perhaps, are comfortable with the inertia of the day-to-day chore of patching the holes in these failing dikes, are content to work on such systems.

— Brian Foote and Joseph Yoder, Big Ball of Mud. Fourth Conference on Patterns Languages of Programs (PLoP ’97/EuroPLoP ’97) Monticello, Illinois, September 1997

I can improve this presentation by having more knowledge about the slides presented (such as the comparison between the two different factories, slicon disk defects, the frequency in different parts of the world). 

 

Image result for japan electricity grid"

 

This is a fascinating new practice called obfuscation where you make a product hard to reverse engineer by hiding its behavior:

Image result for hardware obfuscation circuit"

Software obfuscation:

Image result for software obfuscation"

The silicon lottery involves binning. When you overclock your chips some will max out at 4.3GHZ while others will at 5GHz. They will also require different amounts of power to achieve this. 

The reasons for the difference in the two plants: The San Diego plant emphasized zero defects while Sony of Tokyo, working with a robust quality viewpoint, strove to hit the target value for color density. I can also talk about variations in what is referred to as noise, 1. conditions of use noise (too cold, too hot, wrong voltage, too humid too dry), 2. production variation like of the two factories, 3. wear and deterioration. All these effect idiosyncrasy of products. 

Silicon impurities derive from the crystal growth process if microscopic growth is not uniform it can result in striations. Next, impurities in the silicon (carbon, boron, oxygen, nitrogen). Next, it must be annealed and then lithographically transformed. More info: https://www2.irb.hr/korisnici/icapan/paper.pdf

I also want to add that data rots, and that machines become obsolete so the digital is incredibly material.

Contactless Current Meter (IN PROGRESS)

In line with a series of low-power and energy harvesting devices I would like to make a simple Current Meter which can display the amount of energy being consumed by a given machine in our lab. I imagine the unit as a standalone thing which would use the power it harvests to power itself if possible. 

From https://www.sparkfun.com/products/11005:

Non-Invasive Current Sensor - 30A

The main issue is that this method requires a special power cord which can be split in two like so:

Image result for diy non-invasive current meter"

Using this device to monitor energy  is documented here: https://learn.openenergymonitor.org/electricity-monitoring/ct-sensors/introduction

Ordering this product from the U.S. is not easy at the moment and requires filling in some paper work. It’s also difficult to find european power wires that can be separated into two strands.

hand-powered flashlight (IN PROGRESS)

As part of a series of low-power and power harvesting devices (such as https://steemit.com/technology/@proteus-h/my-diy-passive-mini-radio-microwave-detector), I would like to make a hand-crankable or shakeable torch. I like these projects because they are not too complex, and they demonstrate very tangibly the energy that can be harvested in the environment.

from https://www.kjmagnetics.com/blog.asp?p=shake-flashlight:

 

A Servo makes a nice gear reduction (from https://www.youtube.com/watch?v=9dIkxQ_1H1k):

…and a mini version inside a tic-tac container:

Image result for shake powered flashlight

And a relay coil with a magnet makes a super tiny generator (from https://hackaday.com/2014/01/13/a-simple-led-flashlight-composed-of-a-relay-and-a-magnet/):

I’m curious to try this circuit with the solar engine voltage trigger circuit…Or to make it into another business card version.

Design Primer – Presentation for Digital Fabrication class at UP-Sud December 2019

 

This presentation serves to introduce non-designers to the culture of design. It proposes that design is like a trip, one that should take the designer outside of the “diameter of the obvious” (everything that can be imagined on day 1 and constitutes low-hanging fruit or cliche), to an unexpected place. Every design journey is unique, and this is how it should be – formulaic design is to be avoided at all costs.

The starting place of a design project is some kind of research. This could be in the form of a trip to the museum, an old book of science experiments, a thought experiment, or a found object. Research provides the material against which you push to move in some direction away from your starting place. Because design is new to academia, we usually end up borrowing ideas and data from neighboring disciplines. Research is a time when you should avoid looking at work from other designers, this is research that has already been digested in some sort. We’re looking for primary research at this stage.  (Here I could add something about the perspective you have gained from your new position on your original position – this is art!)

Design involves regular check-ins with your mentors. It’s best to have lots of objects and drawings on your desk for these moments. Many great inventions were discovered by accident (corn flakes, safety glass, the slinky, silly putty, post-it notes, etc.), and having things on your desk allows for misunderstandings and serendipitous associations.

Constraints are a key part of design. Face with a blank canvas, a rule of some kind can provide something tangible to work with. Minimilist works which test out the parameters of a single constraint and curate the results in a series are an example of one design approach. Examples are Sophie Calle’s Chromatic Regime, Sol Lewitt’s variations on open cubes, George Perec’s La Disparition, and Eadweard Muybridge’s Motion Studies. (I should know more about the examples I am bringing up to speak to them with more depth).

Constraints can be self-imposed or can be adopted from a situation. Once the work is prepared for a final presentation, the constraints can be removed like scaffolding from a building or they can be presented to the audience.

Getting stuck in a design process is natural. Brian Eno’s Oblique Strategies, a set of lateral thinking prompts, is a way to inject a foreign thought into your mind at one of these moments which may help you unblock your progress and see things from a different perspective.

Things I would like to add to this presentation:

Representation: How to describe your project? The power of collage and Scale models/scale model photography. One simple, clear idea. Do my images help describe this idea? Start at a large scale then increase when ready. Design your presentation.

Ambiguity being a tool to wield by the designer. The spectacle of the final presentation.

On research, sometimes what is most interesting is isolating a single metric, peeling away lots of data to highlight one metric. (Mauricio taught me this).

On not being precious with your creations: not allowed to destroy what you make, or edit what you make afterwards. Make tons of stuff but don’t identify with what you are making.

More on constraints: Like scaffolding, they can be removed before showing the project. Or, they can become part of the project and be presented at the end. Constraints can either be self-imposed or adopted.

I want to also introduce the concept of sketching, then moving to big scaled all the way to fine scale in the process of the design.

Talk about specificity being your friend (versus making something that does everything). Think about the thing in different situations, different seasons, many peoples, few people, etc.

The side of art/design being about you and how well you know yourself to a certain degree. The fact that this activity is more than a job but a kind of lifestyle. Self-knowledge, maturity…

Synthesizer

 

Karl and I are planning to work on other sides of the ocean on this project together. Karl will continue working on the overall collection and interaction of the modules, I’ll work on prototyping one module at a time. We hope to find a collection of modules that are cool and to see which modules we can make ourselves easily and which we need to buy chips for (such as delay).

The plan is to converge on a prototype with Karl in simulation and me in prototyping. I can mail prototypes for Karl to try in Vancouver and once we have a basic prototype we can move on to test different interfaces, and begin to think about the kit and the cost of the machine. We’re aiming currently for an intermediate level device.

We want to document things well and possibly even produce a collection of music from this device made by Karl’s artist friends. Our collaboration accross the ocean could be a theme in a video we make of the project, for instance.

*******

I am colaborating with Karl Fousek, https://karlfousek.com/, a fantastic Vancouver based sound artist. He proposed the following synth prototype:

Breaking this design up into smaller bits, I have the following designs. They are inspired also by the tinybits modular synth design found here: http://d2q6sbo7w75ef4.cloudfront.net/SYNTH-booklet.pdf

 

*****************

NOISE GENERATION

I tried this but it didn’t work with my 3.3V zener…

 

No dice either! Two more simplish options:

Simple White Noise Generator - EEWeb

Basic discrete white noise generator schematic

I could just generate noise with a microchip: https://forum.arduino.cc/index.php?topic=617302.0

I put this through a high pass filter and here are the results:

This is what the signal looks like before being put through the filter:

****

We have noise! I built the circuit from this site: http://freenrg.info/Physics/Scalar_Vector_Pot_And_Rick_Andersen/Rick_Andersen_Noisegen.htm

I used a 1M trim pot in place of the 470K to tune the noise and used 0.1uF caps in place of 0.047uF, PN2222As in place of 3904, and a 3.9K instead of a 4.7K:

Here’s what is sounds like:

 

************************

 

~~~~~~~~~~~~~~~~~

 

Sample and hold:

https://www.ti.com/product/LF398-N

Which is the circuit below (minus the comparator, I’m using Arduino to generate a pulse every 1ms of 1ms duration):

I’m using two MCP6241 op amps (I tried 741s but they don’t go rail to rail which I think was the issue) powered with 5V. I kind of arbitrarily picked 0.1uF as the C. I’m using an IRF 740. The signal generator is outputing a sine wave with 2V amplitute and a 1V offset.

Here are more screep caps :

With a triangle wave:

 

With noise:

Again with a sine:

 

XOR:

Using an 74LS86 with an arduino generated square wave every millisecond and a sine wave from the function generator, fun and easy!

PART I: OSCILLATOR

Checking to make sure everything works on breadboard first!

Synth on the oscilloscope:

 

I have taken the Atari Punk Console design and made it quickly in Eagle:

This design had two main flaws:

  1. The ground plane was too close to the signal traces, making soldering through hole components very challenging. The moment the soldering iron touches the ground plane it takes all the heat away from the iron and makes it hard to melt the solder.

2. The 3.5mm audio output jack connection was not done properly.

Also: I have also changed to two potentiometers of a different kind.

Here is rev.2:

  

And here is the final product:  

 

Errata:

I still forgot to make a dignified place for a 9V power connection…Oh well.

 

I would like to make a business card version of this circuit, seeing as we have SMD 555 and 556 in the lab!

Here is a first attempt:

 

This synth does not currently work. I think it is the replacement of the 1M pots with 50K pots. I am looking at other 556 circuits which don’t require 1M pots (which are hard to find it would seem). 

This is from the Spark Punk kit: https://core-electronics.com.au/sparkpunk-sound-kit.html

I started with this circuit then added the other modules in the spark punk kit (except the power and amplication parts).

For the frequency dividing I used a JK flip flop 74107 instead of a D-type CD4013 and set it up like so:

Image result for jk flip flop frequency divider"

I also eliminated the switches in the mixer portion (all the outputs are mixed together all the time) and used an LM386 op amp instead of the LM358.

Here is what the circuit looks like set up:

And here is what it sounds like:

Here is the PCB version before populating:

This is from Forrest Mim’s Engineer’s Mini Notebook Stepped-Tone Generator, except I don’t have any 500K pots either…

Here is a diagram that helped me understand how the 555 works:

555 Timer IC How It Works

I am now making a PCB version of the sparkpunk design. Here is the schematic (mostly copied from https://cdn.sparkfun.com/datasheets/Kits/sparkpunk-v13.pdf but with changes for the parts I have and simplified for my situation):

Meanwhile Karl has made a Max 8 patch for me to check out which varies oscillation, filter pass band and resonance (I’m thinking that this means using an inductor to make a filter):

Some important other modules:

noise + sample and hold (check the Art of Electronics)

an envelope generator (allows control of Attack, Sustain, Decay and Release.

simple-synthesis-adsr

Here is one simple design for just attack and decay from https://synthnerd.files.wordpress.com/:

Solar-Powered Autonomous Wildlife Photography

This project uses the LTC3105 Solar Harvesting IC from Linear Technologies, an Atmega328P along with a Serial TTL camera and an SD mini card for saving the images.

The plan is to create a waterproof casing for this device and then install it in a nearby forest and set it to take photographs when it sees movement.

Here is the circuit layout and schematic:

THe LTC3105 can supply between 6mA and 12mA which isn’t enough to power the 3.3V SD card which draws 100mA during R/W at 25MHz mode and 200mA during R/W in 50MHz mode. My attempt to solve this issue is to have a voltage divider step down from 5V (which is powering the camera). The voltage divider uses a 3.3K and a 2.2K resistors and should draw .9mA. The camera has 3.3V TTL logic and draws 75mA at 5V. Both the SD card, the voltage divider and the camera are shut on/off by a MOSFET.

The camera will go on the backside of the circuit board along with a 33x37mm solarbotics solar panel possibly acting as a mini roof. The camera pin spacing is 2mm, not the typical.

I am using two Adafruit tutorials and the relevant preexisting Arduino libraries:

https://learn.adafruit.com/ttl-serial-camera/

https://learn.adafruit.com/adafruit-micro-sd-breakout-board-card-tutorial/introduction

The board took an entire day to engrave and there were still many shorts caused by tiny copper hairs, our lasercutter needs to be serviced:

The first step went smoothly, loading a blink code works fine.

Here things started to get difficult.

  1. I didn’t place the ICP header perfectly square in the middle of the pins and didn’t use an SMD header so the reset pin pulled off. (I only realized this after I replaced the Atmega328 on the board and wasted a perfectly good chip…)
  2. I forgot to add a 10K pull-up for the CS, meaning I guess that the SD card could have been disrupting things.
  3. The soldering of the SD card could have gone smoother, I need to check that the contacts are correct. I am placing the board on a soldering plate and using solder paste that melts at around 130 C.
  4. I really need a USART connection to be able to debug this and didn’t break out pins RX and TX unfortunately. My improvised solution might be adding noise to the serial communication.
  5. It appears that when the SD card is plugged in it is not a good idea to program the Atmega328. I get errors when AVR studio writes or reads data.
  6. Of course don’t forget to set the CLKDIV fuse off so that everything works smoothly with Arduino.

After testing with the SD Arduino libraries I had varied success, sometimes it would pass the SD card initialization but then report the wrong size of SD card. I reformated my SD card and that didn’t change anything. I tried a Read Write example code and that didn’t pass the initialization phase.


I found a serious error in my board, I connected both VDD and VSS to 3.3V but in fact only VDD should go to 3.3V. VSS should be connected to ground.

I can get the Ardiuno SD Read/Write code to at least create a file on the SD card now but it also produced a bunch of USART noise:

I’m not sure if the issues are related to my improvised USART connection or something more fundamental in the circuit.


I put the SD card and the Atmega328 on the same power supply, and also checked the connections between the SD card and the microchip (I added a bit of solder to the MOSI pin which wasn’t passing the continuity test with certainty) and now things seem to be working!

As a quick test it seems that if the SD card and the micro share the same ground everything still works even if the SD card is being supplied with a different VCC.

I added the camera and everything seems to work:

And here is the image quality:

And here’s what the current setup looks like:


Getting to the LTC3105 solar power management part of the circuit and have made some errors:

I want LDO (voltage for microchip) to be at 3.3V so it is at the same logic level as the SD card and camera which it will be communicating with. This means I need a resistor divider to select this voltage level. To get 3.3V I am using 1M and 430K (it adds 1V to the ratio).

To set the Vout at 5V I am using 1M+82K and 270K on the other side.

The solar harvester appears to be working! I’m using a single 1F 5.5V super capacitor which is basically two capacitors put together into one package:

The 1F 5.5V super capacitor I am using isn’t performing great, the moment the sun hits a cloud the voltage falls fast. It might be because of the internal resistance of the cap which is 500mOhms. Contrast this with the wasm 10F 3V supercapacitors I used for the RF solar-powered sensor which had only 34mOhms of ESR. However, the fall in stored power might also be related to the fact I’m asking the LTC3105 to bring Vout to 5V, previously I had only tested to 3.3V. I am also using a solar panel in the 3.5V range which is outside the optimal for this chip.


I am now stuck after having soldered the MOSFET and tried to load the code that would test the SD card after having turned on the MOSFET. This involved also a voltage divider connected to Vout which I am not too sure about. I removed the MOSFET and voltage divider and I am still finding a voltage reaching the SD card mysteriously. I think there may be a short between the 3.3V SD card power and a logic pin for instance.

I think I should have used a voltage regulator instead of a resistor divider, Vout fluctuates quite a bit and this may be throwing off the communication with the SD card.

As a sanity check I powered the SD card with a power supply and the microchip with the super cap/LTC3105 and everything works.

I’m using a 3.3V voltage regulator called the LM3480IM3X-3.3/NOPB which can supply 100mA which is just enough for R/W if the SD card is in 25MHz mode.

The SD card works when being powered from the solar cap if it has a voltage regulator. The VR works up until around 4.3V of capacitor charge.

The camera also works, including in motion capture mode. (All these tests are connected to a power supply simulating the solar panel, I’ve yet to have a sunny day for testing. When I disconnect the power the cap drains super fast but I think this is because I’m using a 1F cap which is leaking heavily. I have also not yet tested the MOSFET to turn on and off the camera and SD card.)

After start up the motion control detects motion even if there isn’t any but then appears to settle down later.

I got several photos of my hand which was waving quickly through the camera’s field which I thought was impressive:

But I also got some strange lighting:

…and at least a quarter of the jpegs were corrupt.


Finished the redesign of the board:

Side one:

Side two:

It has the following improvements over Rev.1:

-A USART friendly plug-in location for debugging.

-A nicer breakout of the pins (RX, TX, MOSFET GND and VCC) which need to go to the camera on the flip side (they can be bridged with bent pins)

-A 10K on CS line

-A resistor divider to set LDO to other than 2.2V.

-Corrected SD card Vcc and GND connections.

-A 3.3V voltage regulator for the SD card instead of the resistor divider.

-Generally increasing the size of the board and making certain areas a little less squeezed.

-Not a reset button, as there was not enough space, but a RST pin which can be easily touched to a nearby ground pin.

-A set of traces and a header for easy installation of the camera on the back of the board.

The lasercutter is cutting beautifully:

But when I flip the board over to flip the backside I am cutting through and creating holes:

This one barely survived:

I had similar issues with this board unfortunately. 

I jumped ship and made a modular version, thinking that this would be fool proof:

 

Tiny aside: Wow, a camera which gets energy from the same light it is recording! https://www.discovermagazine.com/technology/this-camera-is-powered-by-light

Drawing Machine

We wanted to make an interactive Draw Bot which would make nice drawings near the entrance of the Fab Lab and invite guests to upload their own drawings too. I am working with our PhD candidate Nawel Khenak on this project.

We downloaded most of the 3D parts from this kit on Thingiverse: https://www.thingiverse.com/thing:798076

But we eventually made our own custom motor mounts by attaching two of these adafruit products together and screwing them into the wall: https://www.adafruit.com/product/1297

We used basic timing pulley wheels (https://www.mcmaster.com/timing-pulley-wheel ) and Nema 17 stepper motors. We spooled a good few meters of the wire to ensure that there wouldn’t be any slipping or running out of line.

After some issues using first a gearbelt (inelegant and not sufficiently flexible), and then a very fine thread (not sufficiently strong), we landed on using conductive thread (https://www.sparkfun.com/products/11791). It is strong and has a nice color also.

We are powering two Easy Stepper Motor Drivers with 12V and using an Arduino Mega.

We’re using Makelangelo for the software: https://github.com/MarginallyClever/Makelangelo-firmware

Image result for makelangelo drawbot interface

In the Arduino code we selected the RUMBA machine and looked at the pinouts for the motor drivers and the servo motor to make the correct connections on the Mega:

#define MAX_MOTORS (5)

#define MOTOR_0_DIR_PIN (55) #define MOTOR_0_STEP_PIN (54) #define MOTOR_0_ENABLE_PIN (38) #define MOTOR_0_LIMIT_SWITCH_PIN (3) /* X min */

#define MOTOR_1_DIR_PIN (61) #define MOTOR_1_STEP_PIN (60) #define MOTOR_1_ENABLE_PIN (56) #define MOTOR_1_LIMIT_SWITCH_PIN (14) /* Y min */

#define MOTOR_2_DIR_PIN (48) #define MOTOR_2_STEP_PIN (46) #define MOTOR_2_ENABLE_PIN (62) #define MOTOR_2_LIMIT_SWITCH_PIN (18) /* Z Min */

#define MOTOR_3_DIR_PIN (28) #define MOTOR_3_STEP_PIN (26) #define MOTOR_3_ENABLE_PIN (24) #define MOTOR_3_LIMIT_SWITCH_PIN (2) /* X Max */

#define MOTOR_4_DIR_PIN (34) #define MOTOR_4_STEP_PIN (36) #define MOTOR_4_ENABLE_PIN (30) #define MOTOR_4_LIMIT_SWITCH_PIN (15) /* Y Max */

#define MAX_BOARD_SERVOS (4) #define SERVO0_PIN (11) /* Servo 1 */ #define SERVO1_PIN (6) #define SERVO2_PIN (5) #define SERVO3_PIN (4)

#define LIMIT_SWITCH_PIN_LEFT (MOTOR_0_LIMIT_SWITCH_PIN) #define LIMIT_SWITCH_PIN_RIGHT (MOTOR_1_LIMIT_SWITCH_PIN)

We commented HAS_LCD from the config file to avoid a problem where the Drawbot gets stuck waiting for the user to click OK on the LCD screen (the “M226” command in the drawing code):

//—————————————————————————— // LCD panels supported //——————————————————————————

#define HAS_LCD // if you have an LCD panel #define HAS_SD // if you have SD card support on your LCD panel (must be on panel?)

// only uncomment one of these options //#define LCD_IS_128X64 // reprapdiscount Full Graphic Smart LCD Controller #define LCD_IS_SMART // reprapdiscount Smart LCD Controller (including XXL model)

Everytime we load the software we need to re-input the parameters of our machine but Nawel is looking into regenerating the Java code with our parameters baked in based on the info at this site: https://github.com/MarginallyClever/Makelangelo-software/wiki/Getting-Started

We are working to rationalize the wire management, right now it’s unsightly:

Currently the wires from the motors go through the ceiling and come through a ceiling tile to our a nifty box that Nawel made.

We are printing Nice clips for wire management: https://www.thingiverse.com/thing:2798689

And also a nice pen-holder that Nawel made:

Fablab RGB LED Sign

 

Image result for new museum new york sanaa

This project has the goal of making the Fab Lab Digiscope location visible from the exterior of the building and meanwhile creating an a display that users can code themselves.

 

After testing with painting tape, it was clear that giant letters made from material would not be sufficient to make the Fablab visible from outside. This led to the idea of illuminating the letters with LEDs.

Each letter will require about 5 meters of LED strip. We chose RGB leds in a strip from Adafruit that were reseanably priced:

https://www.adafruit.com/product/285?length=1

The LEDs are not individually addressable but the strips are RGB and can of course be faded in and out. Because each letter will be a seperate strip, we can have three different colors and brightnesses happening at once, one for each letter. We could potentially design in interface that lets users create animations, or we could invite them to modify the Arduino code directly as well.

Unlike Neopixels the LEDs in a strip will all change color at the same time and there is no microcontroller embedded in the LED strip. An external microcontroller will be needed to vary the PWM signal being sent to the MOSFETs which will control the power for each color in the strips (one for Red, one for Green and the last for Blue). The LEDs are powered by 12V. There are 30 LEDs/meter, 150 LEDs per letter and 450 LEDs in total which will be controlled by one microchip using 9 output pins.

The choice to work with non-addressable RGB LED strips was motivated by the desire to keep the project within a reasonable budget and level of complexity but to also allow users of the fablab to engage with the intricacies of programming three RGB LED colors at varying intensity changing over time. Good taste dictates not having too many garish colors flashing at the same time as well.

In terms of font, I’m thinking something which reflects the history of computation. Proxy lowercase or uppercase:

Inspiration from Troika London:

Image result for the weather yesterday

Image result for new museum new york sanaa

Raster Image Compression/Interlacing/Encoding Index Representation (IN PROGRESS)

How can non experts quickly get an idea of  the way in which our computers see our raster images?

I have previously focused my energy on how vectors are internally represented because I had the impression that pixel-based rasters were always stored in a predictable top to bottom, left to right arrays in computer memory. However, after a bit of Wikipedia research I discovered that pixels in formats JPEG and PNG are resequenced when they are compressed, downsampled/encoded, or prepared to be sent via a slow internet connection. The last process is called (I think?) Interlacing for JPEGs and Progressive Scanning for PNGs. 

This gif from wikipedia describes the Adam7 algorithm sequencing pixels in a 16×16 bitmap image. (https://en.wikipedia.org/wiki/Interlacing_(bitmaps)) – clearly I want to find something which is dependent on user loaded images and does not transform all images equally.

Apparently when JPEGs are Progressively Scanned the resulting sequence of pixels is not the same irrespective of the image. In spectral selection or successive approximation low-frequency components might be sequenced first before higher-frequency components  (citing http://www.libpng.org/pub/png/book/chapter08.html). I.e. the resulting sequence of pixels is not determined by spatial location but by value (color?) of the pixel. 

There also appears to be some zig-zag action that takes place in JPEG encoding (https://en.wikipedia.org/wiki/JPEG) :

So, it might be interesting to look at these images in “exploded index” view (displace the pixels in one dimension to show their place in the index). My plan right now is to use Grasshopper to load an image and be able to manipulate the pixels in space based on their place in the input image index. There appear to be a few different Grasshopper plugins for working with images like Shapediver (https://www.food4rhino.com/app/shapediver), Hedgehog(https://www.food4rhino.com/app/hedgehog) and something developed by Professor Andrew Witt at the GSD which I can’t quite track down at the moment. 

To get the ball rolling though I found a browser-based hex editor called Hexed (https://hexed.it/?hl=en) and began looking at the raw JPEG and PNG data. For PNG the image info is between IDAT and IEND, and there may be several chunks (possibly to make the file more robust in case there is an error in a particular chunk). For JPEG the pixel data is between SOS (0xFF 0xDA) and EOI (0xFF 0xD9). I highlighted one chuck of pixel data in a JPEG image below using Hexed.

I was expecting to find only one image chunk as this image was not saved from Photoshop as “Progressive” but instead I found three chunks. When I save the image as Progressive though I get 9 chunks. Despite saving the image 16×16 with all black pixels I still get a bunch of different hex values for the pixels and I’m not sure why (I thought possibly a CMYK vs RGB situation but a CMYK image at 100% doesn’t make finding a block of pixels with the same value easier for some reason…). So far I am liking PNG files because they are a whole lot smaller.  

 

I just did some tests deleting parts of JPEG and PNG files. I tried removing single bits, and removing chunks. Both resulted in corrupt files which could not be opened.

From https://en.wikipedia.org/wiki/Portable_Network_Graphics:

  • IHDR must be the first chunk; it contains (in this order) the image’s width (4 bytes), height (4 bytes), bit depth (1 byte), color type (1 byte), compression method (1 byte), filter method (1 byte), and interlace method (1 byte) (13 data bytes total).[10]
  • PLTE contains the palette; list of colors.
  • IDAT contains the image, which may be split among multiple IDAT chunks. Such splitting increases filesize slightly, but makes it possible to generate a PNG in a streaming manner. The IDAT chunk contains the actual image data, which is the output stream of the compression algorithm.[11]
  • IEND marks the image end.

If I change the bit value after IHDR I can mess with the width of the image and this leaves a file which is still readable. When I delete multiples of 8 bits from the file it still appears to load fine also and deletes parts of the image and then adds a single row of random colors. 

It looks like the images I have made in Photoshop are 16×16 pixels (256 pixels in total) and have a bit depth of 24. There appear to be three Hex pairs of data per pixel  (for R,G, and B channels[?]) because there are three times as many hex pairs to describe the image pixels as there are pixels in the image (but also confirmed here: http://www.libpng.org/pub/png/book/chapter08.html#png.ch08.div.4). A Hex pair contains 8 bits worth of data, so 24 bits in total per pixel because that is the bit depth at RGB. Changing the Hex values results in different colors. 

Wikipedia says that only the 3 lower bits of each 8 bits of data is used to describe the color…

OK so after reading the PNG specs I am realizing that things are FAR more complicated than I originally assumed. The IDAT pixel data is compressed by the Zlib deflate algorithm and a kind of custom checksum called a CRC is placed at the end. All of this makes it not possible to edit the raw compressed IDAT without first unzipping it and rezipping it with Zlib before reinserting it into the image.

It looks like there is a Python LibZ tool which is described here: https://stackabuse.com/python-zlib-library-tutorial/

There are also people trying to make their own PNGs and documenting their progress on stack exchange:

https://stackoverflow.com/questions/22672112/png-idat-specification?rq=1

Ah, but I also just realized that if I output a file from Photoshop and select uncompressed it will output a hex stream that more or less directly relates to the pixels in the file. 

By making a new image with a single white dot in a field of black I can then move this white dot around by copy pasting FE FE FE (R,G,B) in the sea of 00 00 00. Apparently this doesn’t cause any issues for the CRC. I can also change the color of any individual pixel by finding the triplet of hex pairs that describes that pixel. This appears to work nicely with 16×16 pixel images of black (white not so much?). I can even find the pixels if the image is white:

02 appears to mark every new line, I could 48 bytes between each 02 (divided by 3 = 16, the number of pixels in each row of the image). 

I have no idea why, but I can’t edit the bottom 1/4 of the image, these two pixels represent the limits of what I can edit.

I failed trying to add an additional row of pixels by changing this value in the IHDR (using Tweak PNG to generate the right CRC once I changed the height of the image in this program) then adding 48 pairs of hex numbers into the IDAT and also changing the CRC at the end of the IDAT using Tweak PNG again. 

I did find these nice visuals to describe the PNG files:

https://www.w3.org/TR/2003/REC-PNG-20031110/

***********

After reading a blog post about glitch art and consulting the Image Glitch App page, I decided to give JPEG, TIFF or BMP a try. 

I found a nice program which allows for inspection of various kinds of image formats called Exiftool:

So this program provdes a ton of metadata about a file, but it’s not really optimized for editing pixel info and reloading. Still, this is useful going forward.

Making a B-line directly for image glitching software I found this handsome program Snorpey:

https://snorpey.github.io/jpg-glitch/

 

 

It makes very pretty glitches, I wonder if I can find out how it is working under the hood and comandeer it’s behavior to my ends…

I am looking through the source code for the program Glitch Canvas (which seems to be the inspiration for this app) here: https://github.com/snorpey/glitch-canvas

Under Sources, there is a glitch Jscript code which does the glitching I think. Before the image is edited it appears to be first translated into a byteArray, other things are determined beforehand like the start of the image data at SOS. At the heart of the code is a loop which appears to iterate over the bytes in the array. The three glitch parameters, seed, amount and iteration, 

Here is the code:

“””

import jpgHeaderLength from ‘./jpgHeaderLength’;

export default function ( byteArray, seed, amount, iterationCount ) {
const headerLength = jpgHeaderLength( byteArray );
const maxIndex = byteArray.length – headerLength – 4;

const amountPercent = amount / 100;
const seedPercent = seed / 100;

for ( var iterationIndex = 0; iterationIndex < iterationCount; iterationIndex++ ) {
const minPixelIndex = ( maxIndex / iterationCount * iterationIndex ) | 0;
const maxPixelIndex = ( maxIndex / iterationCount * ( iterationIndex + 1 ) ) | 0;

const delta = maxPixelIndex – minPixelIndex;
let pixelIndex = ( minPixelIndex + delta * seedPercent ) | 0;

if ( pixelIndex > maxIndex ) {
pixelIndex = maxIndex;
}

const indexInByteArray = ~~( headerLength + pixelIndex );

byteArray[indexInByteArray] = ~~( amountPercent * 256 );
}

return byteArray;
}

“””

So to conclude:

  1. iteration: changes how many times the main loop runs. This will impact how many bytes are rewritten in the image data portion of the image (smaller the iteration, the more loops and the more bytes transformed).
  2. seed: changes how many bytes are skipped over each time the loop runs as it moves from the top to the bottom of the pixel data. (larger the parameter, fewer bytes overwritten because more bytes skipped over).
  3. amount: the value of the new byte which is overwritten each time through the loop. (larger the value, larger the byte value the byte is replaced with).

Clearly I need to learn how the images are prepared as a string of bytes now:

  1. Images are converted into Base64 (6 bits per digit)
  2. Then Base64 is converted to an array of bytes (8 bits per digit)
  3. The bytes are overwritten selectively based on the 3 parameters of the glitching. 
  4. The byte array is recoverted into Base 64.
  5. The Base 65 is recoverted into an image.

Quick note: I like this stepping effect that is created, this could be useful for showing sequence.

JPEGs seem to be just as super compressed and complex as PNGs. (Though they do appear to load even when defective which is way cooler than PNGs). I’m curious about BMP, it seems simpler…

Nice ASCII patterns from this BMP.

I started moving towards Processing for a moment there, it can easily load and manipulate image data. But I have the feeling it resamples image data similar to Grasshopper. There are several example of Processing scripts which sort pixels by color in an image. They are cool but they don’t appear to relate to the original sequence of pixels. (https://steemit.com/art/@granturismo89/how-to-make-amazing-glitch-art-with-processing-and-asdf-pixel-sort or http://datamoshing.com/tag/processing/)

Now I am looking at a website which outlines a series of artistic strategies for datamoshing: 

http://jameshconnolly.com/glitchtalk.html

https://www.glitchet.com/resources

I wonder if I can use my wilderness camera somehow…or hack a digital camera?

RAW files offer the most hackability, they can be saved as a byte array with no header. Different formats start their scanlines in different places on the canvas and sequence RGB differently. Apparently RAW non-interleaved files don’t save pixels sequentially but instead have different layers per color?

compressed files are harder to work with, but they seem the most interesting to visualize because they are going to be messing with the original sequence of bytes and removing data and possibly re sequencing bytes in the process?

She manages to interrupt a Adam7 algorithm to inspect after steps 1-2 (pre-compression) somehow…. 

JPEG have a Run Length Encoding (RLE) which groups together the same frequencies. 

visualizing files by opening them as audio files can quickly show you the overall organization: http://blog.animalswithinanimals.com/2008/09/databending-and-glitch-art-primer-part.html

This author suggests don’t add or subtract bytes to files.

Maybe what I want to be doing is to have a simple processing script that draws pixels from an image file (onto a canvas the size of which I can control) based on a string of bytes (representing the same image) that it reads to get the pixel sequence info.

These are some of the encoding algorithms it would be cool to visualize. I need to find some way to determine the sequence in which these algorithms are processing data:

https://en.wikipedia.org/wiki/Run-length_encoding: runs of data (sequences in which the same data value occurs in many consecutive data elements) are stored as a single data value and count, rather than as the original run. (eg. WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW becomes: 12W1B12W3B24W1B14W)

https://en.wikipedia.org/wiki/Entropy_encoding: replaces each fixed-length input symbol with a corresponding codeword; the most common symbols use the shortest codes.

https://en.wikipedia.org/wiki/Huffman_coding: Makes a frequency tree of content.

https://en.wikipedia.org/wiki/Discrete_Fourier_transform: a  frequency domain  representation of the original input sequence.

https://en.wikipedia.org/wiki/DEFLATE

I should check out the program that processes the TTL serial camera images:

https://learn.adafruit.com/ttl-serial-camera?view=all

Page 20 here has a diagram of the hardware compression:

https://www.st.com/content/ccc/resource/technical/document/application_note/group0/a5/9d/22/46/61/6d/4a/ab/DM00356635/files/DM00356635.pdf/jcr:content/translations/en.DM00356635.pdf

**********

New approach: find python code which compresses images and mess with the code to output what I want.

https://github.com/JoshuaEbenezer/huffman_encoding

This code outputs the list of codes and the integer they replace (the length of the code corresponds to the frequency that integer is found in the image).

Here is an output sample:

116 11111111
119 111111101
129 111111100111
132 111111100110
255 111111100101
149 111111100100111
148 111111100100110
142 111111100100101
171 1111111001001001111
173 1111111001001001110
172 1111111001001001101
194 1111111001001001100111
197 11111110010010011001101
190 111111100100100110011001
209 111111100100100110011000111
213 1111111001001001100110001101
224 111111100100100110011000110011
227 1111111001001001100110001100101
233 111111100100100110011000110010011
236 1111111001001001100110001100100101
240 111111100100100110011000110010010011
241 111111100100100110011000110010010010

This diagram explains it all: https://en.wikipedia.org/wiki/Huffman_coding#/media/File:Huffman_coding_visualisation.svg

If I rebuilt the image in grasshopper, and then used the sequence generated by this algorithm, I could alter the grasshopper version of the image based on the algorithm output. I think the effect would not be very interesting though? The other option is to compress the lines of pixels in the image to the same degree they have been compressed by the algorithm. 

Here is a nice article breaking down Huffman encoding: https://medium.com/iecse-hashtag/huffman-coding-compression-basics-in-python-6653cdb4c476

I could write a processing code which loads an BMP, goes through each pixel in the image comparing it to the Huffman table (which has pixel value and code to replace it with) and then create a new image which either makes the original pixels longer (adding the same pixel value to the right, thus displacing adjacent pixels and pushing them around the frame) or makes runs of the same pixel shorter based on the length of the encoded Huffman table value. This would result in an image which is compressed based on the frequency of the various pixels.

Processing seems to be good at this, as with the pixel sorting example by Kim Asendorf:Image result for kim asendorf mountain tour"

And here is a primer for dealing with images in Processing: https://www.processing.org/tutorials/pixels/

The other approach of sampling a JPEG compression chip could head towards this kind of product: http://pdf.datasheetcatalog.com/datasheets/120/130181_DS.pdf

It has a test mode where the user has access to all internal memory.

From https://cscie12.dce.harvard.edu/lecture_notes/2007-08/20080312/slide19.html:

The GIF to the right is twice the size of the GIF to the left because GIF LZW compresses horizontal pixels of the same color:

horizontal linesvertical lines

Here is a nice article on LZW compression: https://marknelson.us/posts/2011/11/08/lzw-revisited.html . Here is a dictionary or look-up table from Alice and Wonderland that was created by the “greedy” algorithm (which looks for the longest string to replace?),

34830 : 'even\n'
34831 : '\nwith t'
34832 : 'the dr'
34833 : 'ream '
34834 : ' of Wo'
34835 : 'onderl'
34836 : 'land'
34837 : 'd of l'
34838 : 'long ag'
34839 : 'go:'

LZW compression apparently outputs the library along with the compression files. So this could be opened in order to see which sequence of pixels is the most oft repeated.
Retro article describing compression techniques: https://www2.cs.duke.edu/courses/spring03/cps296.5/papers/welch_1984_technique_for.pdf

This site has really helpful animations for dictionary creation: http://www.data-compression.com/index.shtml. Check this one out explaining Huffman encoding: 

could try to visualize series of repeated pixel patterns and the "live" processing of these by different algorithms, some greedy others with different priorities?

Check out this stuff on frame buffers:
This is a CRT screen showing it's memory from wikipedia https://en.wikipedia.org/wiki/Framebuffer:

and this is the color palette for an image:
Adaptative 8bits palette sample image.pngAdaptative 8bits palette.png

still from Wikipedia, here is that same image given the wrong color index:


gzthermal is a psuedo heatmap that shows the words that get  compressed and those that don't
 https://encode.su/threads/1889-gzthermal-pseudo-thermal-view-of-Gzip-Deflate-compression-efficiency:
Image result for deflate image compression visualization"

here is a visualization of LZ77 by Canadian programmer   Julia Evanshttps://jvns.ca/blog/2013/10/24/day-16-gzip-plus-poetry-equals-awesome/

Solar Business Cards

Inspired by the various existing designs of PCB business cards, we were inspired to make a similar thing for Fablab Digiscope.So far there have been popular business card projects which have had LED patterns display, have miniature screens, Magic 8-ball prediction capabilities, act as MIDI controllers, others bring up a text file on a computer when pluged in to USB or offer file storage.

Starting with the constraints:

-We have single and double sided small PCB boards which are business card shaped at 76mm x 50.7mm. However there is also the possibility of working in card stock and laminating vinyl-cut double sided copper tape.

-Because it takes at least 15 minutes to make a single raster pass on a board this size (and around 8 passes to completely ablate the copper), chosing a smaller space on the board to actually engrave is the only way to make this project possible with our time constraints. This may also be another opportunity to revisit earlier tests using the lasercutter in vector mode but this time to offset the vector (by how much?) at least once (probably thrice) to make sure their are no copper bridges this time. This would allow more compositional designs.

-We want to have our name and address written on them “Digiscope Fablab, 630 Rue Noetzlin, 91190 Gif-sur-Yvette” or perhaps just our website “https://fablabdigiscope.gitlab.io/” or just perhaps the logo!

-It has to look cool (composition is an element of the PCB business card “genre”) and/or do something cool!

-Business cards have to be flat – but they can of course pop-out and become 3D at some point. This means that anything soldered to the card also has to be flat. The big question is about batteries, they add thickness, weight but also inelegance, in my opinion. Perhaps the power should come from USB?

-it must have a sufficient number of components to look “technological”.

-obviously to be cost effective the price per card definitely can’t exceed a few dollars.

What it could do:

-a usb device which stores important information for fablab users, such as the fablab charter, information about our website, address, etc. in a text file. The problem I have with making usb connectors out of the edge of boards is I find they don’t work very well.

-a mini pair of joysticks and leds to make some kind of light/memory game.

-a very simple 1381 miller solar engine circuit which causes the card to vibrate every few seconds when in the sun. I like this idea because it associates the lab with clean energy and I find the solar kit I made to be the one which interests people the most immediately.

Technically: this would require SMD versions of the 1381/MCP112 (easy), the 2907 (super expensive), the 2222 (super expensive) and, more importantly, an Aluminum Electrolytic Capacitor SMD version of an 2200uF cap (another cap option is to have four 560uF SMD Aluminum Electrolytic caps in parallel). This raises the question if it’s possible to substitute the transistors with MOSFETs or if using through hole components…

This website: https://www.fetchmodus.org/projects/beam/photopopper/ has an interesting circuit which involves switching the transistors for low-gate-turn-on-voltage MOSFETs (DMN2215UDM-7) which are much easier to find in SMD form. The designer also uses gigantic tantalum capacitors (1500uF!) which are flat. These unfortunately cost 7+ euros each on Mouser. However this circuit appears to be represent an SMD version of the classic solar engine. The designer also uses an alternate of the MCP112 voltage trigger in the ISL88001 which require only 160nA to test the voltage.

In terms of cost:

$2 – single solar panel (from Digikey) $1 – ISL88001 $0.4 – DMN2215UDM-7 $2 – vibrating motor (but we have plenty lying around the lab so they are free-ish!) $3 – compact 3000uF capacitor (only .90 for a larger capacitor – how important is it to make it tiny?) $1 – for the circuit board

under $10USD but that’s a little on the expensive side…

Trying to optimize for cost.

$2 – single solar panel (from Digikey) $1 – ISL88001 $0.4 – DMN2215UDM-7 free – vibrating motor (we have plenty lying around the lab so they are free-ish!) $0.6 – 1000uF capacitor (smaller cap maybe will make less annoying vibrations also) $1 – for the circuit board

$5USD total is not horrible?

Here are some tests with the composition:

Here is my first shot at the circuit:

Here is an attempt at the USB version:

I gleaned the circuit from various available online:

From the internet I got some answers about the components in the circuit:

The USB signal operates at around 3.3V D- needs pulling up (via 1K5) to signal the presence of a USB device The current limiting resistors (68ohm) protect the microchip from a large current sink by the zeners and also serve the function of a termination resistor for the USB (which is supposed to be around 20ohms). V-USB is the firmware of choice for turning avrs into USB devices it seems.

I’m interested in finding an aesthetic language with the lasercutter PCB engraving process we have at the lab. My instinct is that by pulling a thin layer of yellow paint into an engraved path we can make some text that will really stand out.

With the single-sided board there is a nice effect when looking from the reverse and seeing the yellowish-looking traces.

I tried to do an acetone transfer on both sides of the PCB but that yeilded poor results.

One thing I discovered is that you can lasercut out text and then pass a soldering iron and solder over it to silver-ize it. This means you can have two “colors”, copper and silver. If the text were thicker the effect would be more striking.

I’m concerned about how easy this will plug into a usb jack. In fact in the single sided mode it’s far too thin to insert so it looks like a double-sided board is required or a usb male connector.

Some tests cutting out of metal fabric/tape:

The only way one of the lasercutter produced boards looks good is when it is crammed with components, then the components visually take precedence over the charred background. I am retrying the business card but in a much smaller area to eliminate the visual effect of the majority of the object being charred fiberglass (it also means we can make more of them faster). I’m doing this on double sided board so it is the right thickness for a usb plug. (The double sided board looks less bad with the copper removed, more like mdf than charred matrix).


The parts have arrived, here is an adapted version of Nick Ames’ circuit (https://www.fetchmodus.org/projects/beam/photopopper/):

Here are the specs for the two special ICS:

And here is the PCB:

It turns out with some testing that with these 2V solar panels the minimum is a couple of panels in series along with a 1000-1500uF normal or SMD tantalum capacitor. I’m rearranging the board to accomodate two solar panels and only one capacitor.

If I could do the order again I would have taken the 4.46V KXOB25-01X8F instead of the 2.07V KXOB25-05X3F-TR and then it might have been possible to pull of the card with only a single panel. It might have been smart to take a lower voltage version of the voltage trigger (2V instead of 2.9V maybe).

For the interest of time it seems silly to engrave a large board only to use a portion for the circuit. It might be possible to cut a smaller board and integrate it into a cardstock business card form. This could be achieved by delaminating a part of the business card and installing the circuit board there.

Here is the board assembled and working (after a long debug which concluded that there was a short under a capacitor in the board. Better checking of the board before soldering being the solution.)

Here are some options for how the circuit could be integrated into a business card:

And here is a mock up of what the card could look like:

Talking with our doctorat student Nawel she had some ideas for how to improve this prototype:

-why not lasercut the card itself, and make the card represent a hybrid of everything that is possible to make in the fablab? Printing the card on card is not easy to do in the lab. -we could 3D print a kind of stand that cool keep the card standing up so that the panels face the sun.

I don’t mind that the card won’t “work” unless it’s sunny, but it would be nice to have a lamp which would allow us to show how it works when there is sun when it is overcast.

The associations with the card that are good for us are the renewable energy element and the designing with a connection to nature. It’s also nice that the card vibrates – the card is suggesting it is associated with dynamism and that the fablab is by extension a dynamic place.

The USB version of the card for me is kind of dead as it leads to a series of driver issues with certain kinds of windows which is not optimal.

Here is a result I am happy with:

Here is how it all fits together and folds to stand upright:

Making the first run of multiples to check how easy the process is.

The effect of having six of these boards in your hard when the sun out is quite something. It’s as if they are a swarm of bees.

I changed the laser lens and got about ten times more power. I switched from 1200DPI to 600DPI and increased power to 8/100/1 from 16/100/1. Here is the 8-bit effect of the DPI change:

I originally thought it would be neat to combine acetone ink transfer with lasercutting but the results were dissapointing:

Here’s the final prototype:

*********

This project clearly needs to move in the direction of paper PCB or acrylic substrates:

Debugging

 

I like to draw out my circuits and then color over the lines after I’ve soldered them or re-checked them.

I really enjoyed this overview of electronics debugging made by MIT TA D. Elliott Williams: http://web.mit.edu/6.101/www/reference/TheArtofDebuggingCircuits.pdf

Here is a summary of the main thinking as I see it:

-Circuits cannot be wrong, if there is a problem it is “either be because you do not understand what you built or you did not build what you understand.”

-You must first understand how a circuit works before you can debug it. If you are using components, understand the datasheets.

-To debug a circuit, first establish what it is doing, this narrows the list of possible errors down considerably.

-Think, what could cause this type of behaviour? Make a list of possible causes and cross them off one by one.

-Get a fresh pair of eyes on your problem.

-Systems are composed of sub-systems. Isolate sub-systems and test them each in isolation.

-Build your circuit neatly and logically, this makes it easy to check connections and reduces noise from entering long wires.

-Use the continuity mode on your multimeter to test connections.

-Make sure you are not misusing your oscilloscope (check the x1/x10, if in DC/AC coupling, that the ground clips are attached to ground, )

-Rebuild your circuit but with all different components on a different breadboard.

RF communication with the RFM12B module

 

(For the working code scroll all the way to the bottom!)

I free-formed a simple RFM12B atmega168 temperature sensor circuit using a 3.7 lithium ion battery I would one day like to solar recharge. Behold!:

Notes: DO for Data Out and DI for Data In, from the perspective of the RFM12B. I’m using a 7cm long antenna because these modules are 868MHz (you can tell the frequency based on the existence or not of a certain capacitor).

The MISO line is dead, the RFM12B is not responding to anything I’m sending it…

The RFM works with 16 bit data and I am currently trying to squeeze two 8 bit data transmissions, this is why I think things are not currently working. This project might be the limit of where it is easy to make one’s own code and when one must rely on code produced by the manufacturer of the chip in question.

An additional problem with the particilar project is the poor documentation by the manufacturer of the RFM12B module. Even the numbering of the registers is not consistent and there are errors in example code.

Here is the (not yet working) TX side code:


// *
// * Atmega168 RFM12B TX
// *
// * Created:
// * Author : FablabDigiscope
// */

#define F_CPU 8000000

#include <avr/io.h>
#include <util/delay.h>

#define NIRQ PB0 // input for nIRQ which goes low after a transmit is received?


void SPI_Init();
void SPI_Transmit(char dataout);
void SPI_Stop();
void rfInit();


int main(void)
{
		SPI_Init();
		SPDR = (0x00); // byte to send
		SPDR = (0x00); // byte to send
		rfInit();
		DDRD = 0b10000000; //LED for RX/TX rec/sent

	while (1)
	{
		char dataout = 0b10011001; // 0x99 //
		

		
		SPI_Transmit(0xB8); //this must precede data, it is the transmit register write command.		
		SPI_Transmit(0xAA); // PREAMBLE
		
		SPI_Transmit(0xB8); //this must precede data, it is the transmit register write command.
		SPI_Transmit(0xAA);
		
		SPI_Transmit(0xB8); //this must precede data, it is the transmit register write command.		
		SPI_Transmit(0xAA);
		
		SPI_Transmit(0xB8); //this must precede data, it is the transmit register write command.		
		SPI_Transmit(0x2D); // SYNC
		
		SPI_Transmit(0xB8); //this must precede data, it is the transmit register write command.
		SPI_Transmit(0xD4); // Network ID


		SPI_Transmit(0xB8); //this must precede data, it is the transmit register write command.
		SPI_Transmit(dataout);
		
		SPI_Transmit(0x00); //
		SPI_Transmit(0xAA); // DUMMY BYTES, optional?
		
		SPI_Transmit(0x00); //
		SPI_Transmit(0xAA);
		
		SPI_Transmit(0x00); //
		SPI_Transmit(0xAA);
		
		SPI_Stop();

		_delay_ms(1);
		
		PORTD = 0b10000000; // turn on LED

	}
}



void SPI_Init()
{
	DDRB = ((1<<DDB2)|(1<<DDB5)|(1<<DDB3)); //SPI pins on port B: SS, SCK, MOSI outputs
	//set MISO as input
	PORTB |= (1<<DDB2); //start with SS high (slave not selected). DO THIS BEFORE BEGINING ISP
	PORTB |= (1<<DDB4); //MISO pull-up activated
	SPCR = ((1<<SPE)|(1<<MSTR)|(1<<SPR1));  // SPI enable, Master enable, f/64. DO THIS AFTER DDR!
}

void SPI_Transmit(char dataout)
{
	//SPI_Transmit
	PORTB &= ~(1<<DDB2); // pull slave select low
	while(PINB & (1<<NIRQ)); // wait until ready signal (low)
	SPDR = (dataout); // byte to send
	while(!(SPSR & (1<<SPIF))); // wait for SPIF transmit flag to be set. After this, SPDR will contain the received byte!
}


void SPI_Stop()
{
	PORTB |= (1<<DDB2); //slave select high
}

void rfInit()
{
	SPI_Transmit(0x80);
	SPI_Transmit(0xE7); //EL (turn on internal data reg.),EF (FIFO rx mode enabled, data and dclk used for data and data clock output),868band,12.0pF
	
	SPI_Transmit(0x82);
	SPI_Transmit(0x39); //er (for rec. mode),!ebb,ET(for rec. mode),ES,EX,!eb,!ew,DC for receiver mode//
	
	SPI_Transmit(0xA6);
	SPI_Transmit(0x40); //frequency select
	
	SPI_Transmit(0xC6);
	SPI_Transmit(0x47); //4.8kbps
	
	SPI_Transmit(0x94);
	SPI_Transmit(0xA0); //VDI,FAST,134kHz,0dBm,-103dBm
	
	SPI_Transmit(0xC2);
	SPI_Transmit(0xAC); //AL,!ml,DIG,DQD4
	
	SPI_Transmit(0xCA);
	SPI_Transmit(0x81); //FIFO8,SYNC,!ff,DR ***** (this must be set to 0xCA83 to rx)
	
	SPI_Transmit(0xCE);
	SPI_Transmit(0xD4); //SYNC=2DD4 ,AG
	
	SPI_Transmit(0xC4);
	SPI_Transmit(0x83); //@PWR,NO RSTRIC,!st,!fi,OE,EN
	
	SPI_Transmit(0x98);
	SPI_Transmit(0x50); //!mp,90kHz,MAX OUT
	
	SPI_Transmit(0xCC);
	SPI_Transmit(0x17); //OB1 , ACOB0, LPX,Iddy,CDDIT,CBW0
	
	SPI_Transmit(0xE0);
	SPI_Transmit(0x00); //NOT USED
	
	SPI_Transmit(0xC8);
	SPI_Transmit(0x00); //NOT USED
	
	SPI_Transmit(0xC0);
	SPI_Transmit(0x40); //1.66MHz,2.2V
}


Here is the (not yet working) RX side of the code:


// *
// * Atmega168 RFM12B RX
// *
// * Created:
// * Author : FablabDigiscope
// */


		#define F_CPU 8000000

		#include <avr/io.h>
		#include <util/delay.h>

		#define NIRQ PB0 // input for nIRQ which goes low after a transmit is received?
		
		void FIFO_Reset();
		void SPI_Transmit(char dataout);
		void SPI_Init();
		void rfInit();
		void SPI_Stop();
		char SPI_Receive();

		int main(void)
		{
		DDRD = 0b10000000; //LED for RX/TX rec/sent
		
		SPI_Init();
		rfInit();


		
	
		
		while (1)
		{
		char storage; 
		SPI_Transmit(0x00);
		SPI_Transmit(0x00);
		
		FIFO_Reset();
		storage = SPI_Receive(); //should get only last byte of message?	
			
		if(storage == 0b10011001) // 0x99
		{
		PORTD = 0b10000000; //turn on LED
		FIFO_Reset();
		}
		SPI_Stop();
		_delay_us(1);
		}
		}




void SPI_Init()
{
	DDRB = ((1<<DDB2)|(1<<DDB5)|(1<<DDB3)); //SPI pins on port B: SS, SCK, MOSI outputs
	//set MISO as input
	PORTB |= (1<<DDB2); //start with SS high (slave not selected). DO THIS BEFORE BEGINING ISP
	PORTB |= (1<<DDB4); //MISO pull-up activated
	SPCR = ((1<<SPE)|(1<<MSTR)|(1<<SPR1));  // SPI enable, Master enable, f/64. DO THIS AFTER DDR!
}

char SPI_Receive() //must be in receive mode for this to work//
{
	char received;
	//SPI_Receive
	PORTB &= ~(1<<DDB2); // pull slave select low
	while(PINB & (1<<NIRQ)); // wait until ready signal (low)
	SPDR = (0xB0); // byte to send
	while(!(SPSR & (1<<SPIF))); // wait for SPIF transmit flag to be set. After this, SPDR will contain the received byte!
	
	while(PINB & (1<<NIRQ)); // wait until ready signal (low)
	SPDR = (0x00); // byte to send
	while(!(SPSR & (1<<SPIF))); // wait for SPIF transmit flag to be set. After this, SPDR will contain the received byte!
	
	received = SPDR;
	return received;
}

void SPI_Transmit(char dataout)
{
	//SPI_Transmit
	PORTB &= ~(1<<DDB2); // pull slave select low
	while(PINB & (1<<NIRQ)); // wait until ready signal (low)
	SPDR = (dataout); // byte to send
	while(!(SPSR & (1<<SPIF))); // wait for SPIF transmit flag to be set. After this, SPDR will contain the received byte!
}

void FIFO_Reset()
{
	SPI_Transmit(0xCA);
	SPI_Transmit(0x81);

	SPI_Transmit(0xCA);
	SPI_Transmit(0x83);
}


void rfInit()
{
	SPI_Transmit(0x80); 
	SPI_Transmit(0xE7); //EL (turn on internal data reg.),EF (FIFO rx mode enabled, data and dclk used for data and data clock output),868band,12.0pF
	
	SPI_Transmit(0x82); 
	SPI_Transmit(0x99); //er (for rec. mode),!ebb,ET(for rec. mode),ES,EX,!eb,!ew,DC for receiver mode//
	
	SPI_Transmit(0xA6); 
	SPI_Transmit(0x40); //frequency select
	
	SPI_Transmit(0xC6); 
	SPI_Transmit(0x47); //4.8kbps
	
	SPI_Transmit(0x94); 
	SPI_Transmit(0xA0); //VDI,FAST,134kHz,0dBm,-103dBm
		
	SPI_Transmit(0xC2); 
	SPI_Transmit(0xAC); //AL,!ml,DIG,DQD4	
	
	SPI_Transmit(0xCA); 
	SPI_Transmit(0x81); //FIFO8,SYNC,!ff,DR ***** (this must be set to 0xCA83 to rx)	
	
	SPI_Transmit(0xCE); 
	SPI_Transmit(0xD4); //SYNC=2DD4 ,AG
		
	SPI_Transmit(0xC4); 
	SPI_Transmit(0x83); //@PWR,NO RSTRIC,!st,!fi,OE,EN	
	
	SPI_Transmit(0x98); 
	SPI_Transmit(0x50); //!mp,90kHz,MAX OUT
		
	SPI_Transmit(0xCC); 
	SPI_Transmit(0x17); //OB1 , ACOB0, LPX,Iddy,CDDIT,CBW0	
	
	SPI_Transmit(0xE0); 
	SPI_Transmit(0x00); //NOT USED	
	
	SPI_Transmit(0xC8); 
	SPI_Transmit(0x00); //NOT USED	
		
	SPI_Transmit(0xC0); 
	SPI_Transmit(0x40); //1.66MHz,2.2V
}

void SPI_Stop()
{
	PORTB |= (1<<DDB2); //slave select high
}



This code works (most of the time!), it’s from http://dlehard.narod.ru/quick_start.pdf, dlehard did a wonderful job making this clear and legible, thank you for your work!

I think the main reason it is working is the fact that it does not rely on the AVR USI but has its own custom 16 bit Write(Cmd) function. This function is straight forward, it takes a 16 bit input and bit bangs the SDO (Microchip input from RFM12B output) one bit at a time while also reading the SDI (Microchip output to RFM12B input) and writing it to the recv variable. It manually does the basic SPI stuff, pulling Chip Select (CS) low and pulling the clock low before putting SDI in the appropriate state and ticking the clock up. The part I had difficulty understanding was the ANDing with 0x8000, now I understand this is a bitmask which looks only at the highest bit in the 16 bit value (0x8000 = 0b1000000000000000) while the loop bitshifts the Cmd to the left each time, ANDing the next bit with 1. ANDing produces a 1 only if A and B are both 1 and otherwise produces a 0, this is why it is useful as a bitmask.

I don’t know how the timing of this SPI setup is controlled but I guess it’s not critical.

The TX side turns on an LED everytime it transmits, the RX side turns on an LED if it receives the byte 0x30.

I was too lazy to get the USART to work with the Atmega168 (I have a previous post on getting it going with an Attiny2313) so that part of the code is commented out.

Here is the RX side:

/*
 * Atmega168 RFM12B rev.2 RX.c
 *
 * Created: 4/30/2019 2:56:31 PM
 * Author : FablabDigiscope
 */ 


#include <avr/io.h>

/* RFM12B INTERFACE */
#define SCK 5 // SPI clock
#define SDO 4 // SPI Data output (RFM12B side)
#define SDI 3 // SPI Data input (RFM12B side)
#define CS 2 // SPI SS (chip select)
#define NIRQ 2 // (PORTD)

/* IO CONTROL */
#define HI(x) PORTB |= (1<<(x))
#define LO(x) PORTB &= ~(1<<(x))


/* LED */
#define LED 6
#define LED_OFF() PORTD &= ~(1<<LED)
#define LED_ON() PORTD |= (1<<LED)

/* USART */
//#define BAUDRATE 25 // 19200 at 8MHz

void portInit() {
	HI(CS);
	HI(SDI);
	LO(SCK);
	DDRB = (1<<CS) | (1<<SDI) | (1<<SCK);
	DDRD = (1<<LED);
}

unsigned int writeCmd(unsigned int cmd) {
	unsigned char i;
	unsigned int recv;
	recv = 0;
	LO(SCK);
	LO(CS);
	
	for(i=0; i<16; i++) {
		if(cmd&0x8000) HI(SDI); else LO(SDI);
		HI(SCK);
		recv<<=1;
		if( PINB&(1<<SDO) ) {
			recv|=0x0001;
		}
		LO(SCK);
		cmd<<=1;
	}
	HI(CS);
	return recv;
}


/* 
void rsInit(unsigned char baud) {
	UBRRL = baud;
	UCSRC = (1<<UCSZ0) | (1<<UCSZ1); // 8N1
	UCSRB = (1<<RXEN) | (1<<TXEN); // enable tx and rx
}
void rsSend(unsigned char data) {
	while( !(UCSRA & (1<<UDRE)));
	UDR = data;
}
unsigned char rsRecv() {
	while( !(UCSRA & (1<<RXC)));
	return UDR;
}
 */

void rfInit() {
	writeCmd(0x80E7); //EL,EF,868band,12.0pF
	writeCmd(0x8299); //er,!ebb,ET,ES,EX,!eb,!ew,DC (bug was here)
	writeCmd(0xA640); //freq select
	writeCmd(0xC647); //4.8kbps
	writeCmd(0x94A0); //VDI,FAST,134kHz,0dBm,-103dBm
	writeCmd(0xC2AC); //AL,!ml,DIG,DQD4
	writeCmd(0xCA81); //FIFO8,SYNC,!ff,DR (FIFO level = 8)
	writeCmd(0xCED4); //SYNC=2DD4;
	writeCmd(0xC483); //@PWR,NO RSTRIC,!st,!fi,OE,EN
	writeCmd(0x9850); //!mp,90kHz,MAX OUT
	writeCmd(0xCC17); //!OB1,!OB0, LPX,!ddy,DDIT,BW0
	writeCmd(0xE000); //NOT USE
	writeCmd(0xC800); //NOT USE
	writeCmd(0xC040); //1.66MHz,2.2V
}

/*
void rfSend(unsigned char data){
	while(PIND&(1<<NIRQ));
	writeCmd(0xB800 + data);
}
*/

unsigned char rfRecv() {
	unsigned int data;
	while(1) {
		data = writeCmd(0x0000);
		if ( (data&0x8000) ) {
			data = writeCmd(0xB000);
			return (data&0x00FF);
		}
	}
}
void FIFOReset() {
	writeCmd(0xCA81);
	writeCmd(0xCA83);
}

int main(void) {

	unsigned char data, i;
	LED_OFF();
	portInit();
	rfInit();
//	rsInit(BAUDRATE); 
	FIFOReset();
	while(1) {
		//waitForData();
		
		for (i=0; i<16; i++) {
			data = rfRecv();
			if (data == 0x30){
			LED_ON(); //delete this
			}
		}
		FIFOReset();
		LED_OFF();
	}
	return 0;
}



Here is the TX side:

/*
 * Atmega168 RFM12B rev.2.c
 *
 * Created: 4/25/2019 5:27:15 PM
 * Author : FablabDigiscope
 */ 

#include <avr/io.h>

/* RFM12B INTERFACE */
#define SCK 5 // SPI clock
#define SDO 4 // SPI Data output (RFM12B side)
#define SDI 3 // SPI Data input (RFM12B side)
#define CS 2 // SPI SS (chip select)
#define NIRQ 2 // (PORTD)

/* IO CONTROL */
#define HI(x) PORTB |= (1<<(x))
#define LO(x) PORTB &= ~(1<<(x))


/* LED */
#define LED 6
#define LED_OFF() PORTD &= ~(1<<LED)
#define LED_ON() PORTD |= (1<<LED)

void portInit() {
	HI(CS);
	HI(SDI);
	LO(SCK);
	DDRB = (1<<CS) | (1<<SDI) | (1<<SCK);
	DDRD = (1<<LED);
}

unsigned int writeCmd(unsigned int cmd) {
	unsigned char i;
	unsigned int recv;
	recv = 0;
	LO(SCK);
	LO(CS);
	
	for(i=0; i<16; i++) {
		if(cmd&0x8000) HI(SDI); else LO(SDI);
		HI(SCK);
		recv<<=1;
		if( PINB&(1<<SDO) ) {
			recv|=0x0001;
		}
		LO(SCK);
		cmd<<=1;
	}
	HI(CS);
	return recv;
}

void rfInit() {
	writeCmd(0x80E7); //EL,EF,868band,12.0pF
	writeCmd(0x8239); //!er,!ebb,ET,ES,EX,!eb,!ew,DC
	writeCmd(0xA640); //frequency select
	writeCmd(0xC647); //4.8kbps
	writeCmd(0x94A0); //VDI,FAST,134kHz,0dBm,-103dBm
	writeCmd(0xC2AC); //AL,!ml,DIG,DQD4
	writeCmd(0xCA81); //FIFO8,SYNC,!ff,DR
	writeCmd(0xCED4); //SYNC=2DD4,AG
	writeCmd(0xC483); //@PWR,NO RSTRIC,!st,!fi,OE,EN
	writeCmd(0x9850); //!mp,90kHz,MAX OUT
	writeCmd(0xCC17); //OB1,ACOB0, LPX,Iddy,CDDIT,CBW0
	writeCmd(0xE000); //NOT USED
	writeCmd(0xC800); //NOT USED
	writeCmd(0xC040); //1.66MHz,2.2V
}


void rfSend(unsigned char data){
	while(PIND&(1<<NIRQ));
	writeCmd(0xB800 + data);
}


int main() {
	volatile unsigned int i,j;
	asm("cli");
	for(i=0;i<1000;i++)for(j=0;j<123;j++);
	portInit();
	rfInit();
	while(1){
		LED_ON();
		writeCmd(0x0000);
		rfSend(0xAA); // PREAMBLE
		rfSend(0xAA);
		rfSend(0xAA);
		rfSend(0x2D); // SYNC
		rfSend(0xD4);
		for(i=0; i<16; i++) {
			rfSend(0x30+i);
		}
		rfSend(0xAA); // DUMMY BYTES
		rfSend(0xAA);
		rfSend(0xAA);
		LED_OFF();
		for(i=0; i<10000; i++) // some not very
		for(j=0; j<123; j++); // sophisticated delay
	}
}


And here’s a photo of the two modules communicating when each is battery powered from two 1.5 watch battery cells. They continue to be able to communicate after a shortish but not insignificant walk to the coffee machine (50 meters or so).

Here is the code for one RFM12B taking an analog measurement and sending it to the other which is printing the result via USART to a serial port.

TX side:


/*
 * Atmega168 RFM12B TX rev.2.c
 *
 * Created: 4/25/2019 5:27:15 PM
 * Author : FablabDigiscope
 */ 

#include <avr/io.h>

/* RFM12B INTERFACE */
#define SCK 5 // SPI clock
#define SDO 4 // SPI Data output (RFM12B side)
#define SDI 3 // SPI Data input (RFM12B side)
#define CS 2 // SPI SS (chip select)
#define NIRQ 2 // (PORTD)

/* IO CONTROL */
#define HI(x) PORTB |= (1<<(x))
#define LO(x) PORTB &= ~(1<<(x))


/* LED */
#define LED 6
#define LED_OFF() PORTD &= ~(1<<LED)
#define LED_ON() PORTD |= (1<<LED)

void analogInit() {
	ADMUX |= (1 << REFS0); // AREF ref voltage connected to power
	// PC0 input select
	ADCSRA |= (1 << ADPS2) | (1 << ADPS0); // set clock to 32 divisions for 8MHz
	ADCSRA |= (1 << ADEN); /* enable ADC */
	
	
}

unsigned int analogRead() {
	uint16_t adcValue; //16 bit variable because the ADC on the Attiny84 is 10 bits.
	ADCSRA |= (1 << ADSC); /* start conversion */
	adcValue = ADC; /* store high byte into adcValue */
	return adcValue;
}


void portInit() {
	HI(CS);
	HI(SDI);
	LO(SCK);
	DDRB = (1<<CS) | (1<<SDI) | (1<<SCK);
	DDRD = (1<<LED);
}

unsigned int writeCmd(unsigned int cmd) {
	unsigned char i;
	unsigned int recv;
	recv = 0;
	LO(SCK);
	LO(CS);
	
	for(i=0; i<16; i++) {
		if(cmd&0x8000) HI(SDI); else LO(SDI);
		HI(SCK);
		recv<<=1;
		if( PINB&(1<<SDO) ) {
			recv|=0x0001;
		}
		LO(SCK);
		cmd<<=1;
	}
	HI(CS);
	return recv;
}

void rfInit() {
	writeCmd(0x80E7); //EL,EF,868band,12.0pF
	writeCmd(0x8239); //!er,!ebb,ET,ES,EX,!eb,!ew,DC
	writeCmd(0xA640); //frequency select
	writeCmd(0xC647); //4.8kbps
	writeCmd(0x94A0); //VDI,FAST,134kHz,0dBm,-103dBm
	writeCmd(0xC2AC); //AL,!ml,DIG,DQD4
	writeCmd(0xCA81); //FIFO8,SYNC,!ff,DR
	writeCmd(0xCED4); //SYNC=2DD4,AG
	writeCmd(0xC483); //@PWR,NO RSTRIC,!st,!fi,OE,EN
	writeCmd(0x9850); //!mp,90kHz,MAX OUT
	writeCmd(0xCC17); //OB1,ACOB0, LPX,Iddy,CDDIT,CBW0
	writeCmd(0xE000); //NOT USED
	writeCmd(0xC800); //NOT USED
	writeCmd(0xC040); //1.66MHz,2.2V
}


void rfSend(unsigned char data){
	while(PIND&(1<<NIRQ));
	writeCmd(0xB800 + data);
}


int main() {
	volatile unsigned int i,j;
	asm("cli");
	for(i=0;i<1000;i++)for(j=0;j<123;j++);
	portInit();
	analogInit();
	rfInit();
	while(1){
		LED_ON();
		writeCmd(0x0000);
		rfSend(0xAA); // PREAMBLE
		rfSend(0xAA);
		rfSend(0xAA);
		rfSend(0x2D); // SYNC
		rfSend(0xD4);
		for(i=0; i<16; i++) {
			rfSend(analogRead());
		}
		rfSend(0xAA); // DUMMY BYTES
		rfSend(0xAA);
		rfSend(0xAA);
		LED_OFF();
		for(i=0; i<10000; i++) // some not very
		for(j=0; j<123; j++); // sophisticated delay
	}
}

RX side:


/*
 * Atmega168 RFM12B rev.2 RX.c
 *
 * Created: 4/30/2019 2:56:31 PM
 * Author : FablabDigiscope
 */ 


#include <avr/io.h>

/* RFM12B INTERFACE */
#define SCK 5 // SPI clock
#define SDO 4 // SPI Data output (RFM12B side)
#define SDI 3 // SPI Data input (RFM12B side)
#define CS 2 // SPI SS (chip select)
#define NIRQ 2 // (PORTD)

/* IO CONTROL */
#define HI(x) PORTB |= (1<<(x))
#define LO(x) PORTB &= ~(1<<(x))


/* LED */
#define LED 6
#define LED_OFF() PORTD &= ~(1<<LED)
#define LED_ON() PORTD |= (1<<LED)

/* USART */
#define BAUDRATE 25 // 19200 at 8MHz

void portInit() {
	HI(CS);
	HI(SDI);
	LO(SCK);
	DDRB = (1<<CS) | (1<<SDI) | (1<<SCK);
	DDRD = (1<<LED);
}



unsigned int writeCmd(unsigned int cmd) {
	unsigned char i;
	unsigned int recv;
	recv = 0;
	LO(SCK);
	LO(CS);
	
	for(i=0; i<16; i++) {
		if(cmd&0x8000) HI(SDI); else LO(SDI);
		HI(SCK);
		recv<<=1;
		if( PINB&(1<<SDO) ) {
			recv|=0x0001;
		}
		LO(SCK);
		cmd<<=1;
	}
	HI(CS);
	return recv;
}

void rsInit(unsigned char baud) {
	UBRR0L = baud;
	UCSR0C = (1<<UCSZ00) | (1<<UCSZ01); // 8N1
	UCSR0B = (1<<RXEN0) | (1<<TXEN0); // enable tx and rx
}

void rsSend(unsigned char data) {
	while( !(UCSR0A & (1<<UDRE0)));
	UDR0 = data;
}


unsigned char rsRecv() {
	while( !(UCSR0A & (1<<RXC0)));
	return UDR0;
}

/*    FOR ATTINY 2313
void rsInit(unsigned char baud) {
	UBRRL = baud;
	UCSRC = (1<<UCSZ0) | (1<<UCSZ1); // 8N1
	UCSRB = (1<<RXEN) | (1<<TXEN); // enable tx and rx
}
void rsSend(unsigned char data) {
	while( !(UCSRA & (1<<UDRE)));
	UDR = data;
}
unsigned char rsRecv() {
	while( !(UCSRA & (1<<RXC)));
	return UDR;
}
 */

void rfInit() {
	writeCmd(0x80E7); //EL,EF,868band,12.0pF
	writeCmd(0x8299); //er,!ebb,ET,ES,EX,!eb (low batt detector disabled),!ew,DC (bug was here)
	writeCmd(0xA640); //freq select
	writeCmd(0xC647); //4.8kbps
	writeCmd(0x94A0); //VDI,FAST,134kHz,0dBm,-103dBm
	writeCmd(0xC2AC); //AL,!ml,DIG,DQD4
	writeCmd(0xCA81); //FIFO8,SYNC,!ff,DR (FIFO level = 8)
	writeCmd(0xCED4); //SYNC=2DD4;
	writeCmd(0xC483); //@PWR,NO RSTRIC,!st,!fi,OE,EN
	writeCmd(0x9850); //!mp,90kHz,MAX OUT
	writeCmd(0xCC17); //!OB1,!OB0, LPX,!ddy,DDIT,BW0
	writeCmd(0xE000); //NOT USE
	writeCmd(0xC800); //NOT USE
	writeCmd(0xC040); //1.66MHz,2.2V
}


void rfSend(unsigned char data){
	while(PIND&(1<<NIRQ));
	writeCmd(0xB800 + data);
}


unsigned char rfRecv() {
	unsigned int data;
	while(1) {
		data = writeCmd(0x0000); // I think I would add here responses to Status 
		if ( (data&0x8000) ) {
			data = writeCmd(0xB000);
			return (data&0x00FF);
		}
	}
}
void FIFOReset() {
	writeCmd(0xCA81);
	writeCmd(0xCA83);
}

int main(void) {

	unsigned char data, i;
	LED_OFF();
	portInit();
	rfInit();
	rsInit(BAUDRATE); 
	//analogInit();
	FIFOReset();
	while(1) {
		//waitForData();
	for (i=0; i<16; i++) {
		data = rfRecv();
		rsSend(data);
		}
		FIFOReset();
		LED_OFF();
	}
	return 0;
}

I2C Demo Board Design

 

A mockup of the first prototype showing the size and locations of key components and plugs.

This project is inspired by the 8-bit computer of Ben Eater (https://eater.net/8bit/) along with the eccentric PCBs of electronics designers like Teennage Engineering and Bastl instruments. I would like to make a board that is didactic and pedagogical, that can reveal the inner workings of the microcontroller so that students can better understand how they work. I also want the board to be fun, and not dry like typical engineering demo boards. I plan to draw inspiration from the DIP universe of 1990’s through hole components.

Here are a couple of examples of typical demo boards that I found well conceived:

In the end there were so many issues with my initial I2C protoboards that I had added LEDs for each different error type with little notes describing the error in question. This experience also convinced me that it would help to have a dedicated I2C board for first-timers.

Here is the idea in Eagle form.

Mockup of possible component locations.

An information display that goes above the board and is automatically retractable.

Different ways of changing parameters, with jumpers or by attaching crocodile jumpers in different locations, for instance.

A fold out information card and testing different locations for the wires.

The original idea with data tables printed on the board itself.

How should the board stand-up?

An idea about how to incorperate printed information to help the student with reference data.

Figuring out how to minimize the number of extra and unneccessary cables. Here there is only one header per board. Also testing the 7 segment LED display.

Questioning the value of displaying information in bits and or in hex.

A prototype of the kind of information card that could accompany the PCB.

Information about the pertinent registers is shown.

Information about the pertinent bits is shown, but they are laid out in a more readable way.

This last example is a nice balance, it selects the pertinent registers to show but doesn’t give every single last piece of information. Now I have to find a way of relating to the actual components (should they be on the other side or in SMD on the top face?). Also, should the user be able to enter data into the TWDR in hardware? This requires a 8 pin DIP switch and then some way of communicating that the TWDR is either being loaded by the DIP switch or an actual reflection of the contents of the register. Adding a DIP increases the playfulness factor of the board but if it also adds confusion then I’d rather avoid it.

Fab15 part III

Finally have something that works and is easy enough to assemble and work with.Here is the radio side:

Here are the two sides of the sandwhich:

And here is the assembled sandwhich:

I also tried, in vain, to solder a few SMD components by hand. First the DRV8838 motor driver. It’s devilishly tiny and despite proudly soldering tiny wires nothing worked.

With our (expired) solder paste and reflow oven I didn’t get much further either. I’ll wait for our refrigerator to arrive before trying the reflow method again.

I also failed to hand-solder the LUX sensor which was not quite as small but had fragile pads.

I found a note on solarbotics which explained how their 6+V solar panel could be reduced to half the voltage with an exacto knife and a soldering iron here: https://solarbotics.com/product/scc3733/

Most importantly the circuit appears to function. I only have a few revisions to make to the board:

-one of the caps is very close to the traces and needs heat shrink tubing.

-the edge of the radio board next to the MOSFET is too close to the edge and was burned off.

-There was a short between the 1M and the 150K resistors connected to the FB pin of the LTC3105.

-Things are a little tight for the inductor if this SMD component is to be soldered by hand (things are also tight for the other 1206 components next to the IC). Not sure what the plan is for beginners in the workshop here…

-The female headers I’m using aren’t particularly pretty when snipped up and are also too long, making the sandwhich not very compact.

-I need the DRV8838 and the Lux sensor in SOIC or I need solder paste and a fridge.

-Using double sided FR4 is not fun, it’s difficult to cut the second side of copper effectively when you can’t set the focus easily. There is plenty of space on the LTC3105 side of the board for a motor driver.

-Could I find a way to organise the jumper pins between the boards into “banks” so there are just a few rows of pins to solder (instead of individual pins which are prone to brake on this type of board)?

-the through-board antenna works but it is kind of awkward.

-I now have to switch to the RFM69

UPDATE

I’m going to do one more thing before switching to the RFM69, I will make a new board with a motor driver to test the ability to adjust the panel angle.

Here is the plan:

Here is what is already built:

This will involve recutting the LTC3105 circuit but will not require redoing the radio board. This new board will get around the difficulty of doing a double sided board and uses up the unused space on the LTC board. Here is the new LTC3105 circuit which includes the DRV8833 (a motor driver I happen to have which works at 2.7V):

Here is the board (not yet inverted) for cutting:

and here is the circuit diagram in three parts.

The microchip:

The solar harvester:

And the motor driver:

Here is a photo of the final thing cut out:

Here is a photo of me assembling and testing bits at a time:

And here is the RX side of the board freshly cut:

Here’s the board from eagle:

And the schematic:

Here’s the code for the Atmega328 based board to test the USART functionality before soldering the RF module


/*
ATMEGA 328P USART.c

Created: 6/21/2019 10:39:33 AM
Author : FablabDigiscope
 
USB - FTDI 3.3V:
Rx to Tx
Tx to Rx
Gnd to Gnd

(NO LED ON chip's RX, but the one on TX doesn't seem to interfere)

To view your Serial output in AVR Studio, 
1. Click Tools > Data Visualizer
2. Under Configuration>Modules, click External Connection.
3. Double click Serial Port
4. Configure your port. e.g. Set the Baud Rate to 115200
5. Select your COM port
6. Click Connect.

appears to send ASCII from AVR Studio terminal

LED on PC0 blinks when you send a 'j' in serial

 */ 
#define F_CPU 8000000

#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>


#define BAUD 9600                                   // define baud
#define BAUDRATE ((F_CPU)/(BAUD*16UL)-1)            // set baud rate value for UBRR

// function to initialize UART
void uart_init (void)
{
	UBRR0H = (BAUDRATE>>8);                      // shift the register right by 8 bits
	UBRR0L = BAUDRATE;                           // set baud rate
	UCSR0B|= (1<<TXEN0)|(1<<RXEN0);                // enable receiver and transmitter
	UCSR0C|= (1<<UCSZ01)|(1<<UCSZ00);			   // 8bit data format + asynchronous mode
}

// function to send data
void uart_transmit (unsigned char data)
{
	while (!(UCSR0A & (1<<UDRE0)));                // wait while register is free
	UDR0 = data;                                   // load data in the register
}

unsigned char uart_recieve (void)
{
	while(!(UCSR0A) & (1<<RXC0));           // wait while data is being received
	return UDR0;                             // return 8-bit data
}

int main(void)
{
	
DDRC = 0b00000001;
uart_init();

unsigned char a;
    /* Replace with your application code */
    while (1) 
    {
		//transmit
// 	uart_transmit('alpha');
// 	PORTA = 0b00000001;
// 	_delay_ms(1000);
// 	PORTA = 0b00000000;
// 	_delay_ms(1000);

		//recieve
	a = uart_recieve(); 
	_delay_ms(100);
	

	if (a == 'j') //corresponds to a 'j' for instance, but not a 'c'
		{
			PORTC = 0b00000001;
			_delay_ms(1000);
			PORTC = 0b00000000;
			_delay_ms(1000);
			PORTC = 0b00000001;
			_delay_ms(1000);
			PORTC = 0b00000000;
			_delay_ms(1000);	//some kind of local echo thing makes it repeat?? Or else the register is not being cleared
		}
    }
}

Testing parts at time, first the microchip with ISP and LED, then adding the radio, then retesting and finishing the rest of the circuit.

Things to change after this version: add a .1uF capacitor between power for the Atmega328 if using same power as the RF.

The connector for the 3.3V USART plug has gaps and a strange pitch, not a standard header.

Generating code with arduino and uploading it with AVR Studio: Compile the code with Arduino, then make a search for the filename with .hex at the end. Copy this to a convenient location. In AVR Studio you will want to flash a .hex from file location, instead of generating it from a C code. Make sure to let Arduino know that you are using a Pro Mini 3.3V at 8MhZ and make sure you program the CLKDIV fuse to not divide the internal clock by 8. I am using a Arduino pin map image to help with the translation from my pins to the arduino software:

https://www.google.com/url?sa=i&source=images&cd=&ved=2ahUKEwjDtpCx8vriAhVNyxoKHSQLBpEQjRx6BAgBEAU&url=https%3A%2F%2Flearn.sparkfun.com%2Ftutorials%2Fusing-the-arduino-pro-mini-33v%2Fall&psig=AOvVaw2h4IYqUccgSOhJAcis_Tzq&ust=1561217456527846

Here is a helpful website for wiring and the code: https://learn.sparkfun.com/tutorials/rfm69hcw-hookup-guide/all

I’m using LOW POWER LABS’ code for the RF69 here. Make sure to install their two libraries (SPI Flash and RFM69). Here is the code they provide, I have made a tiny modification for the LED pin.

// RFM69HCW Example Sketch
// Send serial input characters from one RFM69 node to another
// Based on RFM69 library sample code by Felix Rusu
// http://LowPowerLab.com/contact
// Modified for RFM69HCW by Mike Grusin, 4/16

// This sketch will show you the basics of using an
// RFM69HCW radio module. SparkFun's part numbers are:
// 915MHz: https://www.sparkfun.com/products/12775
// 434MHz: https://www.sparkfun.com/products/12823

// See the hook-up guide for wiring instructions:
// https://learn.sparkfun.com/tutorials/rfm69hcw-hookup-guide

// Uses the RFM69 library by Felix Rusu, LowPowerLab.com
// Original library: https://www.github.com/lowpowerlab/rfm69
// SparkFun repository: https://github.com/sparkfun/RFM69HCW_Breakout

// Include the RFM69 and SPI libraries:

#include <RFM69.h>
#include <SPI.h>

// Addresses for this node. CHANGE THESE FOR EACH NODE!

#define NETWORKID     0   // Must be the same for all nodes
#define MYNODEID      1   // My node ID
#define TONODEID      2   // Destination node ID

// RFM69 frequency, uncomment the frequency of your module:

//#define FREQUENCY   RF69_433MHZ
#define FREQUENCY     RF69_915MHZ

// AES encryption (or not):

#define ENCRYPT       true // Set to "true" to use encryption
#define ENCRYPTKEY    "TOPSECRETPASSWRD" // Use the same 16-byte key on all nodes

// Use ACKnowledge when sending messages (or not):

#define USEACK        true // Request ACKs or not

// Packet sent/received indicator LED (optional):

#define LED           A0 // LED positive pin


// Create a library object for our RFM69HCW module:

RFM69 radio;

void setup()
{
  // Open a serial port so we can send keystrokes to the module:

  Serial.begin(9600);
  Serial.print("Node ");
  Serial.print(MYNODEID,DEC);
  Serial.println(" ready");  

  // Set up the indicator LED (optional):

  pinMode(LED,OUTPUT);
  digitalWrite(LED,LOW);


  // Initialize the RFM69HCW:

  radio.initialize(FREQUENCY, MYNODEID, NETWORKID);
  radio.setHighPower(); // Always use this for RFM69HCW

  // Turn on encryption if desired:

  if (ENCRYPT)
    radio.encrypt(ENCRYPTKEY);
}

void loop()
{
  // Set up a "buffer" for characters that we'll send:

  static char sendbuffer[62];
  static int sendlength = 0;

  // SENDING

  // In this section, we'll gather serial characters and
  // send them to the other node if we (1) get a carriage return,
  // or (2) the buffer is full (61 characters).

  // If there is any serial input, add it to the buffer:

  if (Serial.available() > 0)
  {
    char input = Serial.read();

    if (input != '\r') // not a carriage return
    {
      sendbuffer[sendlength] = input;
      sendlength++;
    }

    // If the input is a carriage return, or the buffer is full:

    if ((input == '\r') || (sendlength == 61)) // CR or buffer full
    {
      // Send the packet!


      Serial.print("sending to node ");
      Serial.print(TONODEID, DEC);
      Serial.print(", message [");
      for (byte i = 0; i < sendlength; i++)
        Serial.print(sendbuffer[i]);
      Serial.println("]");

      // There are two ways to send packets. If you want
      // acknowledgements, use sendWithRetry():

      if (USEACK)
      {
        if (radio.sendWithRetry(TONODEID, sendbuffer, sendlength))
          Serial.println("ACK received!");
        else
          Serial.println("no ACK received");
      }

      // If you don't need acknowledgements, just use send():

      else // don't use ACK
      {
        radio.send(TONODEID, sendbuffer, sendlength);
      }

      sendlength = 0; // reset the packet
      Blink(LED,10);
    }
  }

  // RECEIVING

  // In this section, we'll check with the RFM69HCW to see
  // if it has received any packets:

  if (radio.receiveDone()) // Got one!
  {
    // Print out the information:

    Serial.print("received from node ");
    Serial.print(radio.SENDERID, DEC);
    Serial.print(", message [");

    // The actual message is contained in the DATA array,
    // and is DATALEN bytes in size:

    for (byte i = 0; i < radio.DATALEN; i++)
      Serial.print((char)radio.DATA[i]);

    // RSSI is the "Receive Signal Strength Indicator",
    // smaller numbers mean higher power.

    Serial.print("], RSSI ");
    Serial.println(radio.RSSI);

    // Send an ACK if requested.
    // (You don't need this code if you're not using ACKs.)

    if (radio.ACKRequested())
    {
      radio.sendACK();
      Serial.println("ACK sent");
    }
    Blink(LED,10);
  }
}

void Blink(byte PIN, int DELAY_MS)
// Blink an LED for a given number of ms
{
  digitalWrite(PIN,HIGH);
  delay(DELAY_MS);
  digitalWrite(PIN,LOW);
}


And here is the one I modified for the RX (it doesn’t have serial so it just blinks when it receives something. However the other board can tell us by serial that it received an ACK)

// RFM69HCW Example Sketch
// Send serial input characters from one RFM69 node to another
// Based on RFM69 library sample code by Felix Rusu
// http://LowPowerLab.com/contact
// Modified for RFM69HCW by Mike Grusin, 4/16

// This sketch will show you the basics of using an
// RFM69HCW radio module. SparkFun's part numbers are:
// 915MHz: https://www.sparkfun.com/products/12775
// 434MHz: https://www.sparkfun.com/products/12823

// See the hook-up guide for wiring instructions:
// https://learn.sparkfun.com/tutorials/rfm69hcw-hookup-guide

// Uses the RFM69 library by Felix Rusu, LowPowerLab.com
// Original library: https://www.github.com/lowpowerlab/rfm69
// SparkFun repository: https://github.com/sparkfun/RFM69HCW_Breakout

// Include the RFM69 and SPI libraries:

#include <RFM69.h>
#include <SPI.h>

// Addresses for this node. CHANGE THESE FOR EACH NODE!

#define NETWORKID     0   // Must be the same for all nodes
#define MYNODEID      2   // My node ID
#define TONODEID      1   // Destination node ID

// RFM69 frequency, uncomment the frequency of your module:

//#define FREQUENCY   RF69_433MHZ
#define FREQUENCY     RF69_915MHZ

// AES encryption (or not):

#define ENCRYPT       true // Set to "true" to use encryption
#define ENCRYPTKEY    "TOPSECRETPASSWRD" // Use the same 16-byte key on all nodes

// Use ACKnowledge when sending messages (or not):

#define USEACK        true // Request ACKs or not

// Packet sent/received indicator LED (optional):

#define LED           14 // LED positive pin


// Create a library object for our RFM69HCW module:

RFM69 radio;

void setup()
{
  // Open a serial port so we can send keystrokes to the module:

  // Set up the indicator LED (optional):

  pinMode(LED,OUTPUT);
  pinMode(7,OUTPUT);
  digitalWrite(LED,LOW);


  // Initialize the RFM69HCW:

  radio.initialize(FREQUENCY, MYNODEID, NETWORKID);
  radio.setHighPower(); // Always use this for RFM69HCW

  // Turn on encryption if desired:

  if (ENCRYPT)
    radio.encrypt(ENCRYPTKEY);
}

void loop()
{

digitalWrite(7, HIGH); // turn on MOSFET

  // RECEIVING

  // In this section, we'll check with the RFM69HCW to see
  // if it has received any packets:

  if (radio.receiveDone()) // Got one!
  {

    if (radio.ACKRequested())
    {
      radio.sendACK();
    }
    Blink(LED,1000);
  }
}

void Blink(byte PIN, int DELAY_MS)
// Blink an LED for a given number of ms
{
  digitalWrite(PIN,HIGH);
  delay(DELAY_MS);
  digitalWrite(PIN,LOW);
}

AVR studio troubles

I am having a very strange problem with AVR Studio. It is having difficulty finding the programmer and, more alarming, it is finding that brand new Atmega 328 chips have all their fuses set to high, most problematically the RSTDSBL fuse which essentially bricks the chips unless you have a high voltage programmer (we don’t).

I replaced my 328p on the board and have the same problem (I did this by holding on to the chip with a pair of tweezers and then using a heat gun in a circle around all the pins until the board fell and I was holding the chip. Then I removed the remaining solder with a solder braid.) After this you have to look under a microscope to make sure no solder schrapnel has been sent across the board to cause a short somewhere.

I’m installed AVR Studio on another computer and am checking to see if the same situation exists. I have replaced my programmer as well as tried with a new jumper cable, nothing is making a difference.

Did a search online and it looks like I need a pull up (10K) on CS so that the RF69 doesn’t introduce gibberish while programming…Yep, that looks like it was it! Updated all boards with a pull-up on CS.

Cool, now everything works, even with the LTC3105 powering the transmitter…but only when connected to the same power supply! Urg.

Nope, now that’s fixed. I was just not giving the reciever enough juice in terms of mA.

Errata: (0.1uF on power and new header for USART also)

This is the Arduino test code I used to make sure the transmitter could function with the LTC3105 based power with an 8 second watchdog timer, it sends the voltage of the cap (I had to remove the MOSFET meant to make this task less wasteful though) and then goes back to charging.


// RFM69HCW Example Sketch
// Send serial input characters from one RFM69 node to another
// Based on RFM69 library sample code by Felix Rusu
// http://LowPowerLab.com/contact
// Modified for RFM69HCW by Mike Grusin, 4/16

// This sketch will show you the basics of using an
// RFM69HCW radio module. SparkFun's part numbers are:
// 915MHz: https://www.sparkfun.com/products/12775
// 434MHz: https://www.sparkfun.com/products/12823

// See the hook-up guide for wiring instructions:
// https://learn.sparkfun.com/tutorials/rfm69hcw-hookup-guide

// Uses the RFM69 library by Felix Rusu, LowPowerLab.com
// Original library: https://www.github.com/lowpowerlab/rfm69
// SparkFun repository: https://github.com/sparkfun/RFM69HCW_Breakout

// Include the RFM69 and SPI libraries:

#include <avr/wdt.h>
#include <RFM69.h>
#include <SPI.h>
#include <avr/sleep.h>

// Addresses for this node. CHANGE THESE FOR EACH NODE!

#define NETWORKID     0   // Must be the same for all nodes
#define MYNODEID      2   // My node ID
#define TONODEID      1   // Destination node ID

// RFM69 frequency, uncomment the frequency of your module:

//#define FREQUENCY   RF69_433MHZ
#define FREQUENCY     RF69_915MHZ

// AES encryption (or not):

#define ENCRYPTKEY    "TOPSECRETPASSWRD" // Use the same 16-byte key on all nodes

// Use ACKnowledge when sending messages (or not):

#define USEACK        true // Request ACKs or not

// Packet sent/received indicator LED (optional):

#define LED          14 // LED positive pin

#define PGOOD         4 // PGOOD

#define VTEST         8 // VTEST MOSFET


// Create a library object for our RFM69HCW module:


int level = 0;

RFM69 radio;

void setup()
{
  // Open a serial port so we can send keystrokes to the module:

   pinMode(LED,OUTPUT);
  digitalWrite(LED,LOW);
    pinMode(7,OUTPUT); //mosfet
    pinMode(PGOOD, INPUT); // PGOOD
  pinMode(A1, INPUT);
   pinMode(LED,OUTPUT);
  pinMode(VTEST,OUTPUT);
  
wdt_enable(WDTO_8S);

  


}

void loop()
{
  digitalWrite(VTEST, HIGH); //turn on MOSFET to read voltage
digitalWrite(7, LOW); // turn off MOSFET
level = digitalRead(PGOOD);
if(level == HIGH)

{
  
  digitalWrite(VTEST, HIGH); //turn on MOSFET to read voltage
  digitalWrite(7, HIGH); // turn on MOSFET
  radio.initialize(FREQUENCY, MYNODEID, NETWORKID);
  radio.setHighPower(); // Always use this for RFM69HCW

  // Turn on encryption if desired:

    radio.encrypt(ENCRYPTKEY);

  

  char Pstr[10];
  char Hstr[10];
  char buffer[50];
  double P = (analogRead(A1)*0.006451); // analog read out of 1023 (based on .975V as highest value), multiply this ratio by 3.33333 to get the actual.
  double H = analogRead(A1);
  
  dtostrf(H, 3,3, Hstr);
  dtostrf(P, 3,3, Pstr);
  
  static int sendlength = strlen(buffer);


sprintf(buffer, "BAT: P:%sV H:%s", Pstr, Hstr);

   
      radio.sendWithRetry(TONODEID, buffer, sendlength);
      Blink(LED,1000);
     level = LOW;
     sleep();
}
  else
  {
   
  digitalWrite(7, LOW); // turn off MOSFET
  sleep();
  }

}
void Blink(byte PIN, int DELAY_MS)
// Blink an LED for a given number of ms
{
  digitalWrite(PIN,HIGH);
  delay(DELAY_MS);
  digitalWrite(PIN,LOW);
}

void sleep(void)
{
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); //select PWR DOWN, the most power savings
  sleep_enable(); //set  SE bit
  sei(); // enable global interrupts
  sleep_cpu(); //actually sleep
  sleep_disable(); //code reaches this point after interrupt
}


The formula for the voltage sensing using a 20K and 10K voltage divider is the following:

((x/1023)*2.2V)*3

I.E. take the analogRead value (which is out of 1023) and multiply it by the maximum 2.2V that could be sensed to get the voltage after the 20K. This is one third of Vcap, so multiply by three to get Vcap. (We need a voltage divider because the microchip is using LDO at 2.2V while the Vout of the RF is getting Vout at 3.3V)

Fab15 part II

Here is the REV.2 board.It’s far more compact, around 38mm x 38mm, and is stackable.

The ICSP acts as a connector linking the top and bottom boards, with one extra pin for the Vout from the LTC3105 to the RF transciever. The idea is to use long pins which will pass through the board but allow a ISCP header to plug in top so it remains programmable.

I have added a ground plane and made sure to make leads thick and short for decoupling caps connected to Vin and Vout.

In this version the solar panels don’t live on a board but instead float above the sandwich.

The board is still basic, it doesn’t allow for PGOOD, SHUTDOWN from LTC3105 nor does it have the diode and cap in series for MPPC. I have also not switched over the the RFM69 as I cannot find anyone who has made it work with the Attiny2313. It does have an I2C LUX sensor included on the solar harvesting board though, it speaks to the microchip on the other board via the ICSP header.

I did a little touching up of the inverted eagle image, I find the ground planing leaves some ugly left over bits. I set distances to .6mm for the ground plane and used .4mm thick traces elsewhere apart from power traces which I made at 1mm. I made the cut out holes .68mm which is the width I measure of a header pin. Making this work nicely will be trail and error I suspect.

I have a hole cut through the top board to allow the antenna to pass through, not sure if this is sacrilege or not but I thought it was nifty.

I have ordered some Attiny2313Vs in SOIC package, LTC3105s, Vishay’s VEML6030 I2C LUX sensor (datasheet: http://www.farnell.com/datasheets/2118174.pdf?_ga=2.101548161.1466299159.1558364926-1966659865.1549463489&_gac=1.82301412.1555072928.Cj0KCQjw7sDlBRC9ARIsAD-pDFol1bBBXfgfW_WkUDGae3GBfZ2j4YvsX5g-ECjGaAFDm9bDDEVXEwgaAkgpEALw_wcB) -I edited the TSL2561 from Sparkfun in Eagle- and some 10F supercapacitors. I have also found a Coilcraft inductor (LPS4018-103MRB) which matches the specs for the LT demo board.

Here’s the board:

And here’s the schematic:

I am also thinking about the indoor/outdoor-ness of this project. If this is placed outdoor it should be potted in resin with maybe a way to strap it to a post or magnetically place it somewhere (is a mini suction cup a real solution?). If there are dual axis motors moving this thing around I could imagine the circuit being inside a kind of clear plexiglass dome, the indoor version wouldn’t need this of course.

So, if everything miraculously works with the circuit I can move to add a dual H-bridge to move this panel around. I could possibly put this on the flip side of one of these double sided boards and use our rivets if necessary…Though I would need to first source some nice motors from one of our approved suppliers. I need a small DC motor with a gear reduction that runs at 3V for 5 euros. Solarbotics seems to be the best source for these, I especially like this https://solarbotics.com/product/gm23/ .

Here is the first attempt at lasercutting on double sided FR4:

Evidently the holes for the passage of pins did not work out. For next time remember that you have to first ablate the metal with the Fiber laser before you can use the C02 laser. Once you get through the fiberglass you need to take out the copper at the reverse side, if you’re using a double sided board, so this requires switching back to the Fiber laser?

In any case, the holes for pins passing through need to be much smaller and the copper traces need to be much bigger. This board will at least serve to test with the newly arrived LTC3105 to see if that circuit can get going.

The parts have arrived, here is the test set up I have got:

The voltage of the small 24 x 33mm solar panel from Solarbotics is around 4.7V, so under the 5V max of the unit. I can confirm that Vin and GND are shorted together by the LTC3105 and so if you see a short there it’s not a problem. I can also confirm that power supplies will give funny readings when supplying the LTC, this appears to be because the device is pulling and pushing current around and making it difficult to tell exactly how much voltage is going where. When I test my solar panels disconnected I get several volts and when I test again while they are plugged in to the LTC I get only a few tens of millivolts.

The 10F supercap is slowly charging, but the light is too strong and is melting the solar panel! I’m concerned that it takes so long to get the LDO going with the solar panels. Using the power supply I can get LDO up and running at very low voltages.

The kxob22 solar cells I am using are super sensitive to soldering temperature, max 220 C for them, this is not enough to melt leaded solder in my experience. I just destroyed 10 of them by accident…

http://ixapps.ixys.com/DataSheet/20110302-KXOB22-12X1-DATA-SHEET.pdf

In principle the idea was to connect four or five in series (plus to minus) to get around 2.5V in total, hitting the efficiency sweet spot of the LTC3105 of 90%+.

Things are looking good charging with a 10V 4700uF cap. It is slowly charging (at 2.8V now) with an Attiny2313V plugged in and waiting for LDO to come on. The Attiny2313 doesn’t seem to be frustrating the charging process, disconnecting it has little effect on the charging. It looks like even when the Vout has reached its target voltage it is not turning on the LDO. Could this be because I accidentally put the Vin too high when testing with the power supply? The datasheet explains that the Vout is not charged until the LDO regulation is met…What’s going on here?

The next question, if this test works, is if a 4700uF cap charged to 3V can power the RFM12B. In previous tests I found that anything less than 2.7V was insufficient for a signal to be received. It looks like it works about 13 of the time with a 4700uF and the Attiny2313V TX circuit I made. With the 10F 3V supercap charged up to 2.9V the RFM12B works nicely…but how to use the LTC3105 to charge such a big cap when it is having difficulty with a .005F….Maybe trying a 0.5F (two 1F 2.5V in series). This works well, no problems transmitting around four times on a full charge. Maybe the magic number is .1F?

WOW! Major change on functionality when I activate MPPC. Almost instantly I hit LDO and start charging the cap. Completely different operation now. Suddenly everything seems possible with this device and this project :). Attaching the RF12B and turning it on once the cap has fully charged successfully sends a trasmission and is fully recharged ten seconds later…Ahh the sweet taste of a working IC.

Moving on to the MOSFET switching, it appears that the microchop voltage of 2V is too low to turn on the transistor very much. I switched to an SMD MOSFET which has a minimum Vgs of 1V and max of 2V. It seems to work now once I add a 10K pull up resistor on the Gate. I’m using the 512-RFD16N05LSM9A.

Replaced the Attiny2313V with an Attiny44A and it’s hogging so much power Vout is decreasing under the same conditions…turns out it’s important to have the microchip exploiting sleep etc.

OK, I’ve got things working such that the moment a HIGH signal is seen by PD6 on the Attiny (from LTC3105’s PGOOD) it beings transmitting. Right now it’s not optimized to use minimal power while waiting but I can work on this next if everything goes smoothly with this test.

Current problem is that once the microchip has slept and let the cap charge up, it sends a transmission and then the cap drains quite rapidly until I hit reset. I think the MOSFET is somehow staying on? I could measure the current draw of the different modules and see whats happening. Another idea is to put the RFM12 initialization AFTER I check that the PGOOD is HIGH.

I have decided to make my life easier and to change to INT1 from PCINT0. INT0 and INT1 can be set up to trigger on RISING or FALLING signals wherease PCINTx only trigger on pin changes, which is causing my code to be more complicated than it needs to be. Here is how the code should work:

The problem with this though is that the interrupt will only work when PGOOD turns on and the state of the pin CHANGES. Once PGOOD is on and stays on it can’t wake up the ATTINY. So before going to sleep the ATTINY needs to make sure PGOOD is OFF (so that it can be awoken by PGOOD going ON). So I need to add a while loop that says which PGOOD is high send transmissions.

I like that this project is making me more connected to the sun. I can’t work without it and I have become much more dependent on good weather to continue working. It makes one think of all the ecology applications this kind of device has too.

Grrrr…wasted an hour plus today learning that in POWER_DOWN mode only LEVEL interrupts for INT0 and INT1 will function (not rising/falling edge or voltage changes). From IDLE mode these work, however.

Here’s the code which works when testing in isolation. Once I connect INT0 to power it wakes up and sends stuff. When reconnected to GND it goes back to sleep to wait for another interrupt. Cool. To get this working with PWR_DOWN I need to add an inverter (as only LOW signal can be detected from deep sleep by INT0 and we get a HIGH from PGOOD).

I have only tested this with a power supply, need to now test with sun (weather didn’t permit this today).

*THIS DOESN’T WORK WITH THE LTC3105. The next code does though further down.

/*
 * Attiny2313 sleep + RFM12B + ltc3105.c
 *
 * Created: 5/27/2019 3:47:37 PM
 * Author : FablabDigiscope
 */ 


#define F_CPU 8000000 

#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>

/* RFM12B INTERFACE */
#define SCK 7 // SPI clock
#define SDO 6 // SPI Data output (RFM12B side)
#define SDI 5 // SPI Data input (RFM12B side)
#define CS 4 // SPI SS (chip select)
#define NIRQ 2 // (PORTD)

/* IO CONTROL */
#define HI(x) PORTB |= (1<<(x))
#define LO(x) PORTB &= ~(1<<(x))


/* MOSFET */
#define MOSFET 4
#define MOSFET_OFF() PORTD &= ~(1<<MOSFET)
#define MOSFET_ON() PORTD |= (1<<MOSFET)


void portInit() 
{
	HI(CS);
	HI(SDI);
	LO(SCK);
	DDRB = (1<<CS) | (1<<SDI) | (1<<SCK);
	DDRD |= (1<<MOSFET);
}

unsigned int writeCmd(unsigned int cmd) 
{
	unsigned char i;
	unsigned int recv;
	recv = 0;
	LO(SCK);
	LO(CS);
	
	for(i=0; i<16; i++) {
		if(cmd&0x8000) HI(SDI); else LO(SDI);
		HI(SCK);
		recv<<=1;
		if( PINB&(1<<SDO) ) {
			recv|=0x0001;
		}
		LO(SCK);
		cmd<<=1;
	}
	HI(CS);
	return recv;
}


void rfInit() 
{
	writeCmd(0x80E7); //EL,EF,868band,12.0pF
	writeCmd(0x8239); //!er,!ebb,ET,ES,EX,!eb,!ew,DC
	writeCmd(0xA640); //frequency select
	writeCmd(0xC647); //4.8kbps
	writeCmd(0x94A0); //VDI,FAST,134kHz,0dBm,-103dBm
	writeCmd(0xC2AC); //AL,!ml,DIG,DQD4
	writeCmd(0xCA81); //FIFO8,SYNC,!ff,DR
	writeCmd(0xCED4); //SYNC=2DD4 ,AG
	writeCmd(0xC483); //@PWR,NO RSTRIC,!st,!fi,OE,EN
	writeCmd(0x9850); //!mp,90kHz,MAX OUT
	writeCmd(0xCC17); //OB1,ACOB0, LPX,Iddy,CDDIT,CBW0
	writeCmd(0xE000); //NOT USED
	writeCmd(0xC800); //NOT USED
	writeCmd(0xC040); //1.66MHz,2.2V
}


void rfSend(unsigned char data)
{
	while(PIND&(1<<NIRQ));
	writeCmd(0xB800 + data);
}


void sleep()
{
	set_sleep_mode(SLEEP_MODE_IDLE); //select PWR DOWN, the most power savings
	sleep_enable(); //set  SE bit
	sei(); // enable global interrupts
	sleep_cpu(); //actually sleep
	sleep_disable(); //code reaches this point after interrupt
}


ISR(INT1_vect) //PB0 level change
{
	//do nothing
}



int main(void)
{

		
			portInit();
			GIMSK |= (1 << INT1); // enable the  external interrupt on pin PD3
			MCUCR |= (1<<ISC11) | (1<<ISC10); //set to rising edge triggered

while(1)
	
	if(PIND & (1<<PD3))
	{
	cli(); 
	
	HI(CS);
	HI(SDI);
	LO(SCK);
			
				MOSFET_ON();
				volatile unsigned int i,j;
				for(i=0;i<1000;i++)for(j=0;j<123;j++);
				rfInit();
				portInit();
				writeCmd(0x0000);
				rfSend(0xAA); // PREAMBLE
				rfSend(0xAA);
				rfSend(0xAA);
				rfSend(0x2D); // SYNC
				rfSend(0xD4);
				for(i=0; i<1; i++) 
				{
					rfSend(0x30+i);
				}
				rfSend(0xAA); // DUMMY BYTES
				rfSend(0xAA);
				rfSend(0xAA);		
				for(i=0; i<10000; i++) // some not very
				for(j=0; j<123; j++); // sophisticated delay
	}

else
{
		MOSFET_OFF();
		sleep();
}
}

So what works well with a power supply does not appear to work well in practice with the LTC3105. Things work the first time then either slowly drain the battery mysteriously or don’t drain the battery at all and sleep on a full capacitor!

Another idea is to have the chip wake up from PGOOD and then just drain the cap until the brown out detector resets the machine when LDO collapses. This is extremely wasteful but is one way to be sure we go from awake state into sleep state based on power levels.

I think one issue is that PGOOD goes up and then down so fast that checking its state in code after it causes an interrupt is not useful.

OK, here it is, the WORKING code! Something happens in the TX code that just continues to drain the cap no matter what kind of interrupt scheme I use so my solution is brute force, reset the entire thing every 8 seconds, poll PGOOD, then transmit until PGOOD goes low or the 8 second reset comes along to wipe the slate clean.


/*
 * Attiny2313 sleep + RFM12B + ltc3105 REV.2.c
 *
 * Created: 5/31/2019 11:21:27 AM
 * Author : FablabDigiscope
 */ 


#define F_CPU 8000000 

#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>

/* RFM12B INTERFACE */
#define SCK 7 // SPI clock
#define SDO 6 // SPI Data output (RFM12B side)
#define SDI 5 // SPI Data input (RFM12B side)
#define CS 4 // SPI SS (chip select)
#define NIRQ 2 // (PORTD)

/* IO CONTROL */
#define HI(x) PORTB |= (1<<(x))
#define LO(x) PORTB &= ~(1<<(x))




/* MOSFET */
#define MOSFET 4
#define MOSFET_OFF() PORTD &= ~(1<<MOSFET)
#define MOSFET_ON() PORTD |= (1<<MOSFET)

volatile unsigned short int flag; // variables that are changed in ISR should be global AND volatile

void portInit() 
{
	HI(CS);
	HI(SDI);
	LO(SCK);
	DDRB = (1<<CS) | (1<<SDI) | (1<<SCK);
	DDRD |= (1<<MOSFET);
}

unsigned int writeCmd(unsigned int cmd) 
{
	unsigned char i;
	unsigned int recv;
	recv = 0;
	LO(SCK);
	LO(CS);
	
	for(i=0; i<16; i++) {
		if(cmd&0x8000) HI(SDI); else LO(SDI);
		HI(SCK);
		recv<<=1;
		if( PINB&(1<<SDO) ) {
			recv|=0x0001;
		}
		LO(SCK);
		cmd<<=1;
	}
	HI(CS);
	return recv;
}


void rfInit() 
{
	writeCmd(0x80E7); //EL,EF,868band,12.0pF
	writeCmd(0x8239); //!er,!ebb,ET,ES,EX,!eb,!ew,DC
	writeCmd(0xA640); //frequency select
	writeCmd(0xC647); //4.8kbps
	writeCmd(0x94A0); //VDI,FAST,134kHz,0dBm,-103dBm
	writeCmd(0xC2AC); //AL,!ml,DIG,DQD4
	writeCmd(0xCA81); //FIFO8,SYNC,!ff,DR
	writeCmd(0xCED4); //SYNC=2DD4 ,AG
	writeCmd(0xC483); //@PWR,NO RSTRIC,!st,!fi,OE,EN
	writeCmd(0x9850); //!mp,90kHz,MAX OUT
	writeCmd(0xCC17); //OB1,ACOB0, LPX,Iddy,CDDIT,CBW0
	writeCmd(0xE000); //NOT USED
	writeCmd(0xC800); //NOT USED
	writeCmd(0xC040); //1.66MHz,2.2V
}

void sleep()
{
	set_sleep_mode(SLEEP_MODE_PWR_DOWN); //select PWR DOWN, the most power savings
	sleep_enable(); //set  SE bit
	sei(); // enable global interrupts
	sleep_cpu(); //actually sleep
	sleep_disable(); //code reaches this point after interrupt
}



void rfSend(unsigned char data)
{
	while(PIND&(1<<NIRQ));
	writeCmd(0xB800 + data); //TX is ready
}



void initWTD(void)
{
	WDTCSR |= (1<<WDE); //enable Watchdog Timer RESET MODE
	WDTCSR |= (1<<WDP3) | (1<<WDP0); //set to 8 seconds
	sei();//enable global interrupts
}


void shutdown()
{
		HI(CS);
		HI(SDI);
		HI(SCK);
		MOSFET_OFF();	
}

// ISR(WDT_OVERFLOW_vect) //PD3 level change
// {
// 	if(PIND& (1<<PD3))
// 	{
// 	flag = flag + 1;
// 	}
// 	else
// 	{
// 	flag = 0;	
// 	}
// 
// }



int main(void)
{
	
	 initWTD();
				
		while(1)
		{
			DDRD |= (1<<MOSFET); // get rid of this if code not working!
			shutdown();
			
					if(PIND &(1<<PD3))
					{
					portInit();
					MOSFET_ON();
					volatile unsigned int i,j;
					for(i=0;i<1000;i++)for(j=0;j<123;j++);
					rfInit();
					portInit();
					writeCmd(0x0000);
					rfSend(0xAA); // PREAMBLE
					rfSend(0xAA);
					rfSend(0xAA);
					rfSend(0x2D); // SYNC
					rfSend(0xD4);
					for(i=0; i<16; i++)
					{
						rfSend(0x30+i);
					}
					rfSend(0xAA); // DUMMY BYTES
					rfSend(0xAA);
					rfSend(0xAA);
					for(i=0; i<10000; i++) // some not very
					for(j=0; j<123; j++); // sophisticated delay
					}											
					
					else
					{
						shutdown();
						sleep();
					}
}
}

Here is the code flow diagram:

Some random things I learned about interrupts:

-keep ISRs short and sweet, preferably just to set a flag or get out of sleep. Don’t use delay or call functions within an ISR. -level sensing is the only interrupt that still works for INT0 and INT1 in deep sleep (power-down mode) -the watchdog timer can save you from getting stuck in a piece of code. -the watchdog timer can sleep you for a maximum of 8 seconds.

Just for fun I tested if the LTC3105 could power an h-bridge and turn a motor. While it can power a motor directly, the transistors I was using were consuming massive amounts when off (more than 100mV). I moved to using a mosfet to turn on/off the entire h-bridge but ran into trouble here. I think my best option is to make a practice h-bridge pcb circuit which uses the low VGS MOSFETs we have in the lab. These will include noise reduction and pull down resistors.

UPDATE

Curiously the radio works even better when the RF module is plugged-in to LDO and the microchip is plugged in to Vout…In either case the microchip draws around 2 to 3.5mA and the RF module draws between 13 and 23mA. Taking off the LED from the MOSFET pin improves performance and adding a code that would check PGOOD is still good after a minute would makes things even better I would assume.

UPDATE

Here is the Rev.4 board based on a mirrored sandwhich principle one slice of which is double-sided. The boards include DRV8837 motor drivers which work with low voltages (http://www.ti.com/lit/ds/symlink/drv8837.pdf). It operates on a motor power supply voltage from 0 to 11 V, and a device power supply voltage of 1.8 V to 7 V and a sleep pin. The only difficulty is the package size which will require the use of the reflow oven. The idea with the drivers is to run a pair of motors to adjust the angle of the panels. This will be a first test to see if this is feasable but I don’t doubt that 1/2F cap has enough juice to run a small DC gearmotor for less than a second.

Here is the schematic which shows the three seperate circuits:

And here is how I imagine everything coming together:

Here are the Rev.5 boards, they are on double sided FR1. Cutting all the way through is not nice but the quality of the cut side is very nice. I lost a trace while cleaning but otherwise these turned out well.

And here is the backside of the microchip board. I didn’t do a sufficient number of passes and had to go around with an exacto knife to finish it off.

REFLOWING

The VEML6030 datasheet explains the maximum temperatures for reflow:

I am using the XG-Z40 solder paste: https://www.mouser.com/datasheet/2/265/tds-4860P-952714.pdf

  • Continued on the following page…

Fab15 part I

pHere is the video explaining the intention of the workshop:

https://vimeo.com/336378467

New idea of using 0ohm jumpers to isolate sub sections of the circuit. This allowed me to test the RF side independent of the LTC3105 side which turned out to be very useful.

Took about 5 or 6 passes on the lasercutter, 20 minutes per pass as it was 100x60mm in size.

BIG things to change:

1.) I am seeing a short between Vin and GND of the LTC3105…which them magically is no longer a short. The resistance I measure between Vin and GND changes between around 100K, to a few hundred ohms, to a handful of ohms. I notice the same thing on other LTC3105 boards I have soldered. When I plug in the IC to a power supply it shorts. I fear I may have destroyed the IC during soldering, though I limited the soldering iron temperature to 300C and never applied it for more than a few seconds at a time. I have built this circuit about 5 times over the years and have varied the circuit layout -it has never worked-, I wonder if the entire stock of ICs has been compromised at some point.

Rereading the datasheet, it says that an internal N-channel MOSFET connects SW and GND in certain modes while waiting for the inductor current to reach its limit. The inductor is a short to Vin so this might explain the apparent short observed between Vin and GND. The datasheet explains that this mode is reached when Vin is greater than the voltage on the driven output (Vout or Vaux), or when the driven output is less than 1.2V (typical). Essentially it would appear that this device temporarily stores energy inside the inductor, and therefore connecting Vin to GND for short moments is part of its normal operating behavior.

Is it possible that the voltage that the multimeter is using to test conductivity is causing the IC to enter this mode?

Why does my power supply thing there is a short circuit? If the circuit is waiting for the inductor to charge and it is not charging is this because the inductor is broken?

Do I need to attach a load to see this thing working?

2.) the goshdarn ICSP header is mirrored somehow 3.) replace the switch with a button (because it’s RESET silly) 4.) get some Attiny2313V packages 5.) the RFM12B is depreciated, I need to get started on the RFM69…

SMALL things to change:

1.) get rid of double highway exchange of wires with 0 ohm jumpers 2.) be able to isolate ground of ltc3105 (need one more zero jumper where I cut with the exacto) 3.) I should make this thing fit on the board stock size, so I don’t need to cut it down. 4.) it should be WAY smaller and possible modular and stacking 5.) there is no RF12B power LED!! 6.) There should be one function per board, with jumpers that allow for stacking. So much easier to trouble shoot.

Working with the LTC3105

Rereading the datasheet some suggestions I missed the first time around:

-The most efficient Vin possible is around 2.3V with Vout at 3V, Iload at 10mA and LDO at 2.2V. So I should chose solar cells that produce this voltage at normal operating light levels. -The MAX Vin is 5V.

-Suggested components: Low ESR output capacitor between Vout and GND Low DC resistance power inductor of 10uH with a “sufficient saturation current rating”. (Saturation current rating = The value of D.C. current when the inductance decreases to 65% of it’s nominal value.) The coil they use on their demo board is the SUMIDA CDRH3D18NP-100N which has:

Courant CC max.: 900 mA Résistance CC max.: 205 mOhms

D.C.R. of max 205mOhm (typical 164Ohm) and a saturation current of 0.90A at 20C.

4.7uF or larger between LDO and GND 10uF or larger ceramic decoupling cap between Vin and GND 10uF or larger cap between Vout and GND 1uF between AUX and GND

-Special Traces: Vin and Vout pins and decoupling cap: wide and as short as possible. GND traces should be lowest impedance path possible. SW and Vin and inductor traces should be as short and possible.

The TX code (for Attiny2313), thank you to http://dlehard.narod.ru/quick_start.pdf :


/*
 * Attiny2313 RFM12B.c
 *
 * Created: 5/16/2019 12:54:04 PM
 * Author : FablabDigiscope
 */ 

#include <avr/io.h>

/* RFM12B INTERFACE */
#define SCK 7 // SPI clock
#define SDO 6 // SPI Data output (RFM12B side)
#define SDI 5 // SPI Data input (RFM12B side)
#define CS 4 // SPI SS (chip select)
#define NIRQ 2 // (PORTD)

/* IO CONTROL */
#define HI(x) PORTB |= (1<<(x))
#define LO(x) PORTB &= ~(1<<(x))


/* LED */
#define LED 4
#define LED_OFF() PORTD &= ~(1<<LED)
#define LED_ON() PORTD |= (1<<LED)



void portInit() {
	HI(CS);
	HI(SDI);
	LO(SCK);
	DDRB = (1<<CS) | (1<<SDI) | (1<<SCK);
	DDRD = (1<<LED);
}

unsigned int writeCmd(unsigned int cmd) {
	unsigned char i;
	unsigned int recv;
	recv = 0;
	LO(SCK);
	LO(CS);
	
	for(i=0; i<16; i++) {
		if(cmd&0x8000) HI(SDI); else LO(SDI);
		HI(SCK);
		recv<<=1;
		if( PINB&(1<<SDO) ) {
			recv|=0x0001;
		}
		LO(SCK);
		cmd<<=1;
	}
	HI(CS);
	return recv;
}


void rfInit() {
	writeCmd(0x80E7); //EL,EF,868band,12.0pF
	writeCmd(0x8239); //!er,!ebb,ET,ES,EX,!eb,!ew,DC
	writeCmd(0xA640); //frequency select
	writeCmd(0xC647); //4.8kbps
	writeCmd(0x94A0); //VDI,FAST,134kHz,0dBm,-103dBm
	writeCmd(0xC2AC); //AL,!ml,DIG,DQD4
	writeCmd(0xCA81); //FIFO8,SYNC,!ff,DR
	writeCmd(0xCED4); //SYNC=2DD4 ,AG
	writeCmd(0xC483); //@PWR,NO RSTRIC,!st,!fi,OE,EN
	writeCmd(0x9850); //!mp,90kHz,MAX OUT
	writeCmd(0xCC17); //OB1,ACOB0, LPX,Iddy,CDDIT,CBW0
	writeCmd(0xE000); //NOT USED
	writeCmd(0xC800); //NOT USED
	writeCmd(0xC040); //1.66MHz,2.2V
}


void rfSend(unsigned char data){
	while(PIND&(1<<NIRQ));
	writeCmd(0xB800 + data);
}



int main() {
	volatile unsigned int i,j;
	asm("cli");
	for(i=0;i<1000;i++)for(j=0;j<123;j++);
	portInit();
	rfInit();
	while(1){
		LED_ON();
		writeCmd(0x0000);
		rfSend(0xAA); // PREAMBLE
		rfSend(0xAA);
		rfSend(0xAA);
		rfSend(0x2D); // SYNC
		rfSend(0xD4);
		for(i=0; i<16; i++) {
			rfSend(0x30);
		}
		rfSend(0xAA); // DUMMY BYTES
		rfSend(0xAA);
		rfSend(0xAA);
		LED_OFF();
		for(i=0; i<10000; i++) // some not very
		for(j=0; j<123; j++); // sophisticated delay
	}
}

Continued in Fablab15 part deux…

Electronics 101

A series of boards and graphic aids to learn about electronics. The main idea here is that each kit teaching some basic principle of electronics, and that it makes the theory portion of electronics more hands on and fun. The kits themselves should be beautiful, so that the students want to keep them, and therefore continue to have access to the learning they represent. The packaging should be minimal and the idea is to make everything in house. Because we won’t have massive numbers of students we can do small production runs to prepare the kits on a just in time basis using the lasercutter and printer. We can also get the students to help prepare their own kits, by finding the parts and even preparing the boards and packaging.

A secondary goal of this project is to explore the aesthetic potential of our in house making processes.

Here is the overall progression of the course:

The idea is that students gradually move towards microchips but first understand some of their subsystems and the things that they cannot do (amplify sound, for instance). Further to the end of the course compound projects are introduced which combine several different skills put to a specific application.

They go hand in hand with this basic electronics course:

 

I have some new slides which use the analogy of the big city and the beach, and the different kinds of roads that exist between them:

 

Engraving this board takes 1 hour, and will require several passes:

The other option is to convert the board into a series of vectors.

Step 1: Export the board in png image format from eagle. (Unfortunately, ground planes make things more complicated for this process and so I work without them).

Step 2: In photoshop use the magic wand tool to select the outlines of the board.

Step 3: Path> Make Work Path transforms the selectio into a series of vector lines. Hide your original image.

Step 4: Export the vector lines in .SVG file format. I use illustrator to examine the vectors and check for errors.

Step 5: Open the .SVG file and resize it (Corel Draw will have changed the size) to the correct size. Convert the line weights to “hairline”.

This produces a different effect.

Unfortunately it doesn’t cut after 5 passes with 16/100/1 in Vector mode!

Here are the inserts for the kits:

Here are the bags for the kits:

I like the idea of using the packaging as a place where information can be stored.

Using Acetone and a printed sheet of A4 I transfered the ink to the card, of course everything has to be printed mirrored!

I prefer this way of laying out information than a tiny book with staples, it seems more practical.

Here is the instruction manual for the 8-bit register kit:

Here is the instruction manual for the logic gates kit:

Here are the other instructions:

And here is a C primer which I’m also working on:

Some ideas about how to learn to code C:

-online code bebuggers

-modular code with unit testing

-println() + LEDs

-AVR Studio breakpoints

 

Fab 15 part IV

 

// RFM69HCW Example Sketch
// Send serial input characters from one RFM69 node to another
// Based on RFM69 library sample code by Felix Rusu
// http://LowPowerLab.com/contact
// Modified for RFM69HCW by Mike Grusin, 4/16

// This sketch will show you the basics of using an
// RFM69HCW radio module. SparkFun's part numbers are:
// 915MHz: https://www.sparkfun.com/products/12775
// 434MHz: https://www.sparkfun.com/products/12823

// See the hook-up guide for wiring instructions:
// https://learn.sparkfun.com/tutorials/rfm69hcw-hookup-guide

// Uses the RFM69 library by Felix Rusu, LowPowerLab.com
// Original library: https://www.github.com/lowpowerlab/rfm69
// SparkFun repository: https://github.com/sparkfun/RFM69HCW_Breakout

// Include the RFM69 and SPI libraries:
#include <Wire.h>
#include <LSM303.h>
#include <avr/wdt.h>
#include <RFM69.h>
#include <SPI.h>
#include <avr/sleep.h>

LSM303 compass;

// Addresses for this node. CHANGE THESE FOR EACH NODE!

#define NETWORKID     0   // Must be the same for all nodes
#define MYNODEID      2   // My node ID
#define TONODEID      1   // Destination node ID

// RFM69 frequency, uncomment the frequency of your module:

//#define FREQUENCY   RF69_433MHZ
#define FREQUENCY     RF69_915MHZ

// AES encryption (or not):

#define ENCRYPTKEY    "TOPSECRETPASSWRD" // Use the same 16-byte key on all nodes

// Use ACKnowledge when sending messages (or not):

#define USEACK        true // Request ACKs or not

// Packet sent/received indicator LED (optional):

#define LED          14 // LED positive pin

#define PGOOD         4 // PGOOD

#define VTEST         8 // VTEST MOSFET


// Create a library object for our RFM69HCW module:


int level = 0;

RFM69 radio;

void setup()
{
  // Open a serial port so we can send keystrokes to the module:
  Wire.begin();
  compass.init();
  compass.enableDefault();
    compass.m_min = (LSM303::vector<int16_t>){-32767, -32767, -32767};
  compass.m_max = (LSM303::vector<int16_t>){+32767, +32767, +32767};
  
   pinMode(LED,OUTPUT);
  digitalWrite(LED,LOW);
    pinMode(7,OUTPUT); //mosfet
    pinMode(PGOOD, INPUT); // PGOOD
  pinMode(A1, INPUT);
   pinMode(LED,OUTPUT);
  pinMode(VTEST,OUTPUT);
  
wdt_enable(WDTO_8S);

  


}

void loop()
{
  digitalWrite(VTEST, HIGH); //turn on MOSFET to read voltage
digitalWrite(7, LOW); // turn off MOSFET
level = digitalRead(PGOOD);
if(level == HIGH)

{
  
  digitalWrite(VTEST, HIGH); //turn on MOSFET to read voltage
  digitalWrite(7, HIGH); // turn on MOSFET
  radio.initialize(FREQUENCY, MYNODEID, NETWORKID);
  radio.setHighPower(); // Always use this for RFM69HCW

  // Turn on encryption if desired:

    radio.encrypt(ENCRYPTKEY);

   compass.read();
   double H = compass.heading();

  char Pstr[10];
  char Hstr[10];
  char buffer[50];
  double P = (analogRead(A1)*0.006451); // analog read out of 1023 (based on .975V as highest value), multiply this ratio by 3.33333 to get the actual.
  
  dtostrf(H, 3,3, Hstr);
  dtostrf(P, 3,3, Pstr);
  
  static int sendlength = strlen(buffer);


sprintf(buffer, "BAT: Power:%sV Heading:%s", Pstr, Hstr);

   
      radio.sendWithRetry(TONODEID, buffer, sendlength);
      Blink(LED,1000);
     level = LOW;
     sleep();
}
  else
  {
   
  digitalWrite(7, LOW); // turn off MOSFET
  sleep();
  }

}
void Blink(byte PIN, int DELAY_MS)
// Blink an LED for a given number of ms
{
  digitalWrite(PIN,HIGH);
  delay(DELAY_MS);
  digitalWrite(PIN,LOW);
}

void sleep(void)
{
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); //select PWR DOWN, the most power savings
  sleep_enable(); //set  SE bit
  sei(); // enable global interrupts
  sleep_cpu(); //actually sleep
  sleep_disable(); //code reaches this point after interrupt
}



Errata:

-I used SDA and SCL for motor driving but they should have been kept for I2C sensor reading.

-can’t use XTAL in arduino software environment (PB6 and PB7)

-I should have picked up a LUX sensor which already has readily available libraries AND is in stock, such as the VEML7700

-Because soldering tiny components is difficult and not fun I am considering eliminating the compass from the project. If the user sets the device to point north on start up it can track itself knowing the rotation of the motors.

And this code uses both the compass and the lux sensor, sharing the same lines.

This is the Lux sensor I’m using:

https://www.adafruit.com/product/1980

And I’m getting the temperature (and received transmission power reading) from inside the RF69.

I’m also reading two photodiodes and turning two motors. The photodiodes are set up like so: https://electronics.stackexchange.com/questions/73732/how-to-use-sfh235-ir-photodiode-correctly




// RFM69HCW Example Sketch
// Send serial input characters from one RFM69 node to another
// Based on RFM69 library sample code by Felix Rusu
// http://LowPowerLab.com/contact
// Modified for RFM69HCW by Mike Grusin, 4/16

// This sketch will show you the basics of using an
// RFM69HCW radio module. SparkFun's part numbers are:
// 915MHz: https://www.sparkfun.com/products/12775
// 434MHz: https://www.sparkfun.com/products/12823

// See the hook-up guide for wiring instructions:
// https://learn.sparkfun.com/tutorials/rfm69hcw-hookup-guide

// Uses the RFM69 library by Felix Rusu, LowPowerLab.com
// Original library: https://www.github.com/lowpowerlab/rfm69
// SparkFun repository: https://github.com/sparkfun/RFM69HCW_Breakout

// Include the RFM69 and SPI libraries:
#include "Adafruit_TCS34725.h"
#include <Wire.h>
#include <LSM303.h>
#include <avr/wdt.h>
#include <RFM69.h>
#include <SPI.h>
#include <avr/sleep.h>

LSM303 compass;

// Addresses for this node. CHANGE THESE FOR EACH NODE!

#define NETWORKID     0   // Must be the same for all nodes
#define MYNODEID      2   // My node ID
#define TONODEID      1   // Destination node ID

// RFM69 frequency, uncomment the frequency of your module:

//#define FREQUENCY   RF69_433MHZ
#define FREQUENCY     RF69_915MHZ

// AES encryption (or not):

#define ENCRYPTKEY    "TOPSECRETPASSWRD" // Use the same 16-byte key on all nodes

// Use ACKnowledge when sending messages (or not):

#define USEACK        true // Request ACKs or not

// Packet sent/received indicator LED (optional):

#define LED          14 // LED positive pin

#define PGOOD         4 // PGOOD

#define VTEST         8 // VTEST MOSFET


// Create a library object for our RFM69HCW module:


int level = 0;

RFM69 radio;

Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_700MS, TCS34725_GAIN_1X);

void setup()
{
  // Open a serial port so we can send keystrokes to the module:
  Wire.begin();
  compass.init();
  compass.enableDefault();
    compass.m_min = (LSM303::vector<int16_t>){-32767, -32767, -32767};
  compass.m_max = (LSM303::vector<int16_t>){+32767, +32767, +32767};
  
   pinMode(LED,OUTPUT);
  digitalWrite(LED,LOW);
    pinMode(7,OUTPUT); //mosfet
    pinMode(PGOOD, INPUT); // PGOOD
  pinMode(A1, INPUT);
   pinMode(LED,OUTPUT);
  pinMode(VTEST,OUTPUT);

  pinMode(0, OUTPUT); //motors
  pinMode(1, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);

  pinMode(A2, INPUT);
  pinMode(A3, INPUT);
  
wdt_enable(WDTO_8S);

   tcs.begin();
    
  


}

void loop()
{
  uint16_t r, g, b, c, colorTemp, L;
  
  digitalWrite(VTEST, HIGH); //turn on MOSFET to read voltage
digitalWrite(7, LOW); // turn off MOSFET
level = digitalRead(PGOOD);
if(level == HIGH)

{
  
  digitalWrite(VTEST, HIGH); //turn on MOSFET to read voltage
  digitalWrite(7, HIGH); // turn on MOSFET
  radio.initialize(FREQUENCY, MYNODEID, NETWORKID);
  radio.setHighPower(); // Always use this for RFM69HCW

  // Turn on encryption if desired:

    radio.encrypt(ENCRYPTKEY);

   compass.read();
   double H = compass.heading();

   double T = radio.readTemperature();


 char Leftstr[10];
 char Rightstr[10];

 char Tstr[10];
  char Pstr[10];
  char Hstr[10];
   char Lstr[10];
  char buffer[50];

  
  double P = (analogRead(A1)*0.006451); // analog read out of 1023 (based on .975V as highest value), multiply this ratio by 3.33333 to get the actual.


  tcs.getRawData(&r, &g, &b, &c);
  // colorTemp = tcs.calculateColorTemperature(r, g, b);
  colorTemp = tcs.calculateColorTemperature_dn40(r, g, b, c);
  L = tcs.calculateLux(r, g, b);

  double left = analogRead(A3);
  double right = analogRead(A2);

 dtostrf(left, 3,3, Leftstr);
 dtostrf(right, 3,3, Rightstr);
   
  dtostrf(T, 3,3, Tstr);
  dtostrf(H, 3,3, Hstr);
  dtostrf(P, 3,3, Pstr);
  dtostrf(L, 3,3, Lstr);
   
  static int sendlength = strlen(buffer);




sprintf(buffer, "B:%sV H:%s Lx:%s T:%s L:%s R:%s", Pstr, Hstr, Lstr, Tstr, Leftstr, Rightstr);

   
      radio.sendWithRetry(TONODEID, buffer, sendlength);


  if(left>right)
  {
    digitalWrite(0, HIGH);
    digitalWrite(1, LOW);
    digitalWrite(5, HIGH);
    digitalWrite(6, LOW);
    delay(1000);
  }
  else
  {
    digitalWrite(0, LOW);
    digitalWrite(1, HIGH);
    digitalWrite(5, LOW);
    digitalWrite(6, HIGH);
    delay(1000);
  }
      
      Blink(LED,1000);
     level = LOW;
     sleep();
}
  else
  {
   
  digitalWrite(7, LOW); // turn off MOSFET
  sleep();
  }

}
void Blink(byte PIN, int DELAY_MS)
// Blink an LED for a given number of ms
{
  digitalWrite(PIN,HIGH);
  delay(DELAY_MS);
  digitalWrite(PIN,LOW);
}

void sleep(void)
{
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); //select PWR DOWN, the most power savings
  sleep_enable(); //set  SE bit
  sei(); // enable global interrupts
  sleep_cpu(); //actually sleep
  sleep_disable(); //code reaches this point after interrupt
}



I am making the BOM list now for the conference. Here is the list of components so far (all in 1206 and hand-solderable packages):

Solar Cell SCC3733 3.3V FTDI Cable MOMENTARY-SWITCH-SPST-SMD-6.2MM-TALL Atmega328P TQFP RFM69HCW Wireless Transceiver – 915MHz solid core wire for antenna Single + double row detachable male headers jumpers of various types (male to female, female to female, male to male) DRV8833 Motor Driver HTSSOP LTC3105 MSOP VEML7700 Lux Sensor Short female double row headers RED LED 1206 GREEN LED 1206 N-CHANNEL POWER MOSFET 2.7V 1F Supercapacitor 647-JUWT1105MCD 10uH Inductor 994-MSS5131-103MLC Photodiode BPW34 Micro Gearmotor – 175 RPM (6-12V) Atmel ICE programmer Gear Motor 23 – 1:192 Offset Shaft GM23 Gear Motor 24 – 1:192 90 Degree Shaft GM24

0.1uF 33pF 10uF 1uF 4.7uF 500K 2.2K 1M 240K 150K 499K 1M 20K 0K 10K 500K 2.2K 1M 240K 150K 499K 1M 20K 0K

And here is a 3D print of how gearmotors could be used to make a two axis panel tilt set up.

And here is the newest version of the board:

Errata: SDA and SCL switched on LTC3105 board. Also, the lux sensor I bought VEML6030 doesn’t work. -break out PGOOD to a pin for testing purposes

Other idea for a minimal version of this circuit with attiny84.

Same thing with Atmega328p (getting things to work software side with Attiny + RF69 is tough…)

I’m calling it the wasp (a 10F cap has some sting!). I like that it fits on one board, this solves the most challenging aspect of the last design – connecting a bunch of pins between two boards and dealing with the cubersome thickness that it has in the end. It has less functionality but it has the essential stuff and maybe the rest was not necessary in the end. It’s ready to be embed in resin and strapped to a tree outdoors!

Here is the mould ready to go for resin test:

I’m using this resin: https://www.boutique-resine-epoxy.fr/resine-biosourcee/352-resine-epoxy-sr-greenpoxy-56-durcisseur-sd-surf-clear.html

SR greenPoxy 56 SD GreenPox 505 V2 (catalizer)

The ratio is 1:2, thanks to Remy Ducros for his documentation: http://fabacademy.org/2019/labs/digiscope/students/remy-ducros/assignement/week18/

My plan is to wrap the capacitor in foam so that it can expand if necessary and to keep all the pins accessible (outside the resin) then to put it outside for a while and see if it still works later!


Had an issue where the device needed to be restarted everytime the microchip lost power (overnight for instance). Came up with a fix, here is the new code:



// RFM69HCW Example Sketch
// Send serial input characters from one RFM69 node to another
// Based on RFM69 library sample code by Felix Rusu
// http://LowPowerLab.com/contact
// Modified for RFM69HCW by Mike Grusin, 4/16

// This sketch will show you the basics of using an
// RFM69HCW radio module. SparkFun's part numbers are:
// 915MHz: https://www.sparkfun.com/products/12775
// 434MHz: https://www.sparkfun.com/products/12823

// See the hook-up guide for wiring instructions:
// https://learn.sparkfun.com/tutorials/rfm69hcw-hookup-guide

// Uses the RFM69 library by Felix Rusu, LowPowerLab.com
// Original library: https://www.github.com/lowpowerlab/rfm69
// SparkFun repository: https://github.com/sparkfun/RFM69HCW_Breakout

// Include the RFM69 and SPI libraries:
#include <SPI.h>
#include <avr/wdt.h>
#include <RFM69.h>
#include <avr/sleep.h>



// Addresses for this node. CHANGE THESE FOR EACH NODE!

#define NETWORKID     0   // Must be the same for all nodes
#define MYNODEID      2   // My node ID
#define TONODEID      1   // Destination node ID

// RFM69 frequency, uncomment the frequency of your module:

//#define FREQUENCY   RF69_433MHZ
#define FREQUENCY     RF69_915MHZ

// AES encryption (or not):

#define ENCRYPTKEY    "TOPSECRETPASSWRD" // Use the same 16-byte key on all nodes

// Use ACKnowledge when sending messages (or not):

#define USEACK        true // Request ACKs or not

// Packet sent/received indicator LED (optional):

#define LED          A3 // LED positive pin

#define PGOOD         3 // PGOOD


#define MOSFET      9//


// Create a library object for our RFM69HCW module:


int level;

RFM69 radio;


void setup()
{
  // Open a serial port so we can send keystrokes to the module:

    
    pinMode(LED,OUTPUT);
    digitalWrite(LED,LOW);
    pinMode(MOSFET,OUTPUT); //mosfet    
    pinMode(PGOOD, INPUT); // PGOOD

}

void loop()
{

wdt_enable(WDTO_8S);
 
level = digitalRead(PGOOD);

if(level == HIGH)

{

 char Tstr[10];

  
  digitalWrite(MOSFET, HIGH); // turn on MOSFET
  delay(100);
  radio.initialize(FREQUENCY, MYNODEID, NETWORKID);
  radio.setHighPower(); // Always use this for RFM69HCW

  // Turn on encryption if desired:

    radio.encrypt(ENCRYPTKEY);

   double T = radio.readTemperature();


  char buffer[50];

  
  dtostrf(T, 3,3, Tstr);

   
  static int sendlength = strlen(buffer);




sprintf(buffer, " T:%s", Tstr);

   
      radio.sendWithRetry(TONODEID, buffer, sendlength);


      Blink(LED,100);

}

else
{
sleep();
}

}



void Blink(byte PIN, int DELAY_MS)
// Blink an LED for a given number of ms
{
  digitalWrite(PIN,HIGH);
  delay(DELAY_MS);
  digitalWrite(PIN,LOW);
}

void sleep(void)
{
  digitalWrite(MOSFET, LOW); // turn on MOSFET
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); //select PWR DOWN, the most power savings
  sleep_enable(); //set  SE bit
  sei(); // enable global interrupts
  sleep_cpu(); //actually sleep
  sleep_disable(); //code reaches this point after interrupt
}


I have a new scheme to maintain the flatness of the circuit board but “pop-up” from it. I like the idiosyncratic form it gives:

Here are some of the slides from the workshop itself:

For the TX module A-side:

And for the RX module:

The 1381 Solar Engine

 

 

This circuit (found here: http://solarbotics.net/library/circuits/se_t1_1381.html) works with a MCP112 voltage supervisor to save up solar energy until it is significantly large to make turn a motor. With a small solar panel charging a large capacitor, it is possible to make something move even on an overcast day!

The circuit works by charging the capacitor with a solar panel until it reaches the MCP112’s tripping point (in this circuit I’m using the 2.7V tripping point flavor but they range from 1.8V to 4.38V) at which point the MCP112 activates the PN2222 transistor which powers the motor. The PN2907 turns on at this point and latches the PN2222 in the on position until the capacitor voltage level runs below the PN2907 turn on threshold (of about 0.6V). Without the PN2222 the MCP112 would deactivate at 0.3V below it’s trigger threshold (2.4V in this case).

I’m using a 37x33mm Monocrystalline Solar Cell from Solarbotics.com (https://solarbotics.com/product/scc3733/) which produces 6.7V and 20mA. It is at maximum efficiency of 106.335mW with a load of 300 ohms.

By changing the size of the capacitor from 2200uF to 4700uF you can change the amount of charge that will be passed on to the motor.

On an overcast day the little motor is activated every 5 seconds or so for about half a second, not bad for a tiny solar panel!

Here’s the trace image showing a comparison of the same circuit with different capacitor sizes and voltage trigger flavours:

Neato!

I am interested in using this circuit to power something other than a motor. However, simply replacing the motor with a given circuit (like a microchip) does not work.

Replacing the motor with a 220 ohm resistor appears to allow the circuit to cause an LED to blink and to charge and discharge, however.

The Complete Solar Power Smart Head Rev.3 by Wilf Rigter

Here is a photo of the full assembly in action!

I found the circuit at this website: http://solarbotics.net/library/circuits/bot_head_pshead.html

I am building Wilf Rigter’s 74HC240 circuit but replacing the 74HC240 with two 74HC540s (and replacing the 1381 with a MCP112) because I couldn’t source a 74HC240 from my local electronics store. The two logic chips are inverting octal buffers but the 74HC540 has one enable for all eight inverters while the 74HC740 has two for two sets (A and B in the circuit above). To make the translation, first I connected the two AND input enables of the 74HC540 to behave the same way as the single enable of the 74HC240, then I remapped the pins from one 74HC240 to two 74HC540s.

Here is the comparison of the 74HC240 with the 74HC540 and my remapped circuit:

Once the voltage trigger is reached (2.9V in my case) the MCP112 sends a high signal to inverter 1 which turns on the Standby Flasher circuit.

Meanwhile the High/Low oscillator circuit which was oscillating is pushed into either the clockwise or anticlockwise motor turn configuration depending on the values of the two light dependent resistors (LDRs). Either the low voltage that exists to the bottom will win out or the high voltage that exists at the top.

This configures the motor drivers to turn on the motor in one direction or the other.

I have “air wired” this circuit after redrawing the circuit here:

Here is the play by play of the assembly:

Here is how I glued the solar head to the post:

And here is another circuit which claims to do the same thing but which I failed to make work:

 

 

*********

Making a version 2 following this schematic in SMD version. The goal is to replace the expensive and tech overkill 2DOF sunhead using LTC3105 and atmega developed on this page (https://www.marrs.io/fab-15-part-vii/). This comes with one caveat, I can’t use the cool stepper motor linear actuators I am collecting from CD/DVD drives… I have opened up 15 of these drives and only one came with a DC motor powered laser raft, and it was an ugly plastic mechanism. The other option is for me to design such a linear rail from scratch 3D printing the gears but then I lose the tech recyling angle and add considerable engineering challenge. The benefit is that it costs very little and is a simpler more minimal analog electronics solution. It could work for this design:

 

Here is the SPSH 2DOF circuit:

The different between photodiodes and phototransistors: https://circuitglobe.com/difference-between-photodiode-and-phototransistor.html#:~:text=One%20of%20the%20major%20difference,conversion%20of%20light%20into%20current.

Photodiodes appear to be rare, at least in the lab. Could something like the following turn a phototransistor into a photodiode? By changing the value of R1 you could change the degree of current change?

Phototransistor Output Voltage Circuit connects the phototransistor and 2 k-ohm resistor in series

I could also just buy some photodiodes from Hackspark in Paris, though I would love to make this entirely SMD.

The challenge I want to set myself is to make an SMD version of this circuit. I have 74*540s in SMD, and I plan to build on the business card version of the 1381 solarengine which I’ve built here (https://www.marrs.io/solar-business-cards/). Rewiring the 540 based on the 240s in the original schematics but integrating the SMD solarengine is a possible stumbling block. I am working with the understanding that the solarengine essentially enables the buffer oscillators (instead of powering a motor ), by connecting the enables to low.

 

I’m not sure how easy the wiring is going to be on a single-sided board however…

It turned out to be not too hard, the main issue was not having 10M and 6.2M resistors and having to make them from 1M resistors…As a result the board is larger than I would like (50mmx65mm approx.).

Here’s the completed board:

It’s not currently working, I added a higher power solar cell and a higher capacity cap. The cap is charging and the enable is high (oh wait it should be LOW! This must be the purpose of those extra resistors in the solar engine portion of the circuit. However it still doesn’t work when I pull the enable low artificially…) for the octal buffer but no power is arriving at the motors. So I’m thinking the issue is with the inverting oscillator parts of the circuit.

I removed the SMD solar engine and copied the schematic closely, but still no luck. I’m guessing there is an error or short on my board. I am going to try to breadboard this circuit to see if I have more luck.

It may be simpler to make this circuit twice (from https://www.fetchmodus.org/projects/beam/photopopper/) as I already have everything I need. The circuit is straight forward and there is no analog business:

I just confirmed, the circuit can power the DC gearmotors I’m using well, even with the 1500uF cap. The package of MOSFETs I have comes in doubles so at least that is efficient. It doesn’t look great but my focus right now is the finalize the circuit so I can focus on the design of the sun seeker.

 

Here is the schematic:

After making this didn’t realize that it is for FOUR motors, i.e. there are not two motors which change direction…I tried wiring up the same motor for both and it doesn’t work of course because it’s not an H-bridge.

Here is another option, it would involve 2X this bare bones sun seeker, replacing the 240 with the 540 and the 1381 solar engine with the SMD version I am working with. From http://grant.solarbotics.net/Circuits.htm :

Ok this circuit is dead easy and works reliably so far. It has very few parts also! (Something I didn’t notice last test – it requires at least 4V to operate with these DC gearmotors…I also just tested and LEDs appear to be able to replace photodiodes no problem on the power supply powered breadboard version!)

Here’s the SMD version ready to cut and prototype:

Unfortunately I need probably a larger capacitor and or more solar panels to make this setup work. With the 4700uF and the 6V solar cell everything works great, with either smaller caps or smaller cells there is some movement but very little. In his circuit he uses a 3.4V solar panel and a 3300uF cap so it may be possible to reduce these. 

I’ve come to the realization that the SMD version of the miller engine I am working with doesn’t seem to vibe well with the head seeking circuits. I have been behaving like they are interchangeable but they may not be.

I went back to the breadboard version and included his miller engine. Everything works if you use a super light dc gearmotor (in white) but the gearmotors I am using aren’t happy with the voltage it would appear (so I need a higher 1381 flavor – like G instead of E). So I think this explains why the PCB I made didn’t work. (I tried unplugging the 1381 trigger pin and triggering the 2222 myself once the voltage maxed at 6V and alternating between putting each photodiode in darkness and it gives it a good spin. So I think it is indeed related to the top voltage – motor combination.)

*EDIT*

I have since tried adding a voltage divider to the sensor pin of the 1381 to effectively change the trigger voltage. With this technique it’s possible to make the circuit work with the small metal gearmotors if the voltage trigger is set around 4V+. This means that I could make a simple sunseeking circuit using 2x barebones and metal gear motors + prints! 

I’m testing if this could work with modified Servo motors at the moment as well but so far no luck. 

As for the issue with running those nice steppers with lead screws, it looks like it’s possible to buy DC gearmotors with leadscrews:

Micro Metal DC Geared Motor with Lead Screw (6V 150RPM M4*55) - KD Robot Kit

In parallel I am sketching some other ideas:

This is a double stepper version of a previous prototype. And here are some sketches of mechanisms I’d like to try out:

Attempt to convert a DC gear motor into linear actuator not starting smoothly…

This works nicely – except! – the black LED-style photodiode packages work best and the circuit only works with super tiny DC gear motors…This despite increasing the solar panels from 3V to 6V and it having a capacitance of almost 100,000uF. I don’t know what part of the circuit controls the trigger but this could be something to fiddle with potentially? (See documentation here: http://wilf.solarbotics.net/PSH/heads101.html ). It works super well with those inexpensive 2V garden lamp solar panels!!

Covering one photodiode at a time changes the direction. It’s quite efficient. 

There is another BEAM related circuit to possibly check out…to drive stepper motors! From http://www.redrok.com/beamcircuits.htm

There is also this from http://solarbotics.net/library/circuits/driver_stepper_beamstep.html :

I would need to make this twice however, in order to have 2DOF and therefore have two solarengines which is not ideal. 

Here is the almost finished uchip version of the circuit with 10 solar cells:

Quick look at cost of the entire thing: 

Micro DC metal gearmotors – $14-17 !! (cf with Micro Stepper gearmotor – $5, solarbotics mini motors from $4.50-$9.25, and FREE found motors)

McMaster Carr sprockets – 4$/piece, roller chain $20/foot !

Fancy Solar Cells – $2 x 10 = $20 !! (cf with Solarbotics  22×24 $4.50, 22×33 $6.50, 33×37 – $8, and CHEAP lawn latern panels)

LTC3105 – $5.70 ! (but $3.25 if buy >25) 

Supercap – $2-$4

DRV8833 – $1.25

Clearly recycling old motors and hardware is cost effective, as is finding a cheaper solar panel (taking one from a lawn latern if it’s powerful enough). Avoiding the need for the LTC saves a bit too but not as much as I originally thought.  At bulk the electronics is negligeable and if the parts are all recycled it becomes relatively inexpensive. That said, the cheapest by far is found hardware and solar panel plus a BEAM style 2DOF sun seeker that would come in under $10 easily (especially because the circuit works super well with the garden lamp solar panels at 2V). 

****

I haven’t got the stepper drivers working yet on the board. The 3D print had to be made out of a different material – so the offsets were not perfect. Some parts didn’t survive the printing and assembly as they were too fine also. I also didn’t realize that I have another identical linear actuator but not an identical threaded sliding block.

The two base options side by side:

I am starting to think this project is a little too ambitious! Perhaps a single axis machine, or something with a simple circuit.

****

I tried the SPSH 2DOF again in SMD:

And here’s the circuit for testing: