Electrons
BrowniePi
Art, Electrons, Photons, Project“A terrible idea that should never have been tried!” – Ansel Adams, April 2021.
[/vc_column_text][/vc_column][/vc_row][vc_row][vc_column width=”1/3″][vc_single_image image=”2047″ img_size=”large” onclick=”link_image”][/vc_column][vc_column width=”2/3″][vc_column_text]This image is captured by shooting the film back of a Brownie 620 camera using a Raspberry Pi camera mounted inside the black chamber above the lens just outside the optical path. High gain screen material is used on the image plane to maximize the reflected light. It works, sort of… The current limitations are that it ends up being very low light so in full sun, I have to use the highest ISO available and about a .25 second exposure. Also, since the sensor is not in line, the captured image is skewed and you end up with soft focus on the top and bottom.[/vc_column_text][vc_empty_space height=”100 px”][vc_column_text]First image, un-warped and brightened.[/vc_column_text][/vc_column][/vc_row][vc_row][vc_column][vc_column_text]It’s a fun project, and I’m sure I’ll complete it someday. I am waiting to see if a higher sensitivity chip will become available for the RPI. Ultimately, the best solution would be to manufacture a lens element that would refocus the 120 film size beam onto the small sensor mounted in the back, or a concave mirror on the back that would reflect the image onto the sensor where it is currently mounted (both of these solutions are beyond my pay grade).This uses a Raspberry Pi Zero W and a small LCD panel, both powered by a Pi Sugar battery. Operating system is diet pi. The camera is operated with the buttons on the LCD panel board and the resulting image is displayed on the screen. Using VNC and a virtual desktop, I also get the live feed directly from the camera to a laptop. The pictures are saved with the raw information and converted to DNG. I designed a 3D printed adapter to mount the electronic components on the body of the camera but I am waiting on more light sensitive solutions to finish the piece.
My completely unsorted code is here: https://github.com/thomashollier/browniePi
[/vc_column_text][/vc_column][/vc_row][vc_row el_class=”th_flexrow”][vc_column width=”1/3″ el_class=”th_flexpictures”][vc_single_image image=”2049″ img_size=”large”][/vc_column][vc_column width=”1/3″][vc_single_image image=”2051″ img_size=”large” el_class=”th_flexpictures”][/vc_column][vc_column width=”1/3″ el_class=”th_flexpictures”][vc_single_image image=”2050″ img_size=”large” el_class=”th_flexpictures”][/vc_column][/vc_row]Memory or Memento?
Art, Atoms, Collection, Electrons, ThoughtsOne is the ghost in our minds of a past sensory experience and the other is a physical thing we hope can be a gateway to the first. Does the promise of preserving memories destroy them by creating an unmanageable clutter of infinite possibilities which merge into a cold immaterial surface offering no comfort and condemning us to anxiety?
We want to reclaim power over defining the topology of our interior landscapes. It involves art, hammers, digital storage, authentication, originals, blood, and an evening of fun with people.
[/vc_column_text][/vc_column][/vc_row][vc_row][vc_column width=”1/4″][vc_single_image image=”2012″ img_size=”full”][/vc_column][vc_column width=”1/2″][vc_single_image image=”2004″ img_size=”full” alignment=”center”][/vc_column][vc_column width=”1/4″][vc_single_image image=”2011″ img_size=”full” alignment=”right”][/vc_column][/vc_row]
[vc_row el_class=”th_collection-row” css=”.vc_custom_1615843473810{margin-right: 60px !important;margin-left: 60px !important;}”][vc_column][vc_column_text el_class=”th_collection-title”]Sketchz, 2014-2020[/vc_column_text][vc_column_text el_class=”th_collection-media”]Processing Sketches, Custom Linux, PyQT, Teensy, wood, glass.[/vc_column_text][vc_video link=”https://player.vimeo.com/video/510531613″ el_width=”70″ align=”center” css=”.vc_custom_1617002091343{margin-top: 40px !important;}”][/vc_column][/vc_row][vc_row css=”.vc_custom_1609467915356{margin-top: 40px !important;padding-right: 10% !important;padding-left: 10% !important;background-color: #101616 !important;}”][vc_column][vc_row_inner][vc_column_inner][vc_column_text]
Displaying algorithmic art
[/vc_column_text][vc_column_text]The design work for this custom display device started around 2014. At that time, I was developing algorithmic art and growing dissatisfied with the lack of means to show it outside the usual computing context. Seeing a mouse and keyboard open up this kind of imagery in a window over a familiar desktop OS on the usual computer hardware dilutes the nature of the experience.[/vc_column_text][/vc_column_inner][/vc_row_inner][vc_column_text]These pieces typically involve coming up with a set of rules that describe how the image is drawn and how it animates. Random variations are introduced in the input parameters and end up generating different versions, each unique but all clearly belonging to the same family. After studying them for a while, you get an intuitive feel for the underlying process shaping them and you automatically start to anticipate how they will continue to develop. A tension develops back and forth between the expectation of the viewer and the validation (or not) of those expectations in the visuals, like watching crashing waves on the shore.
Each iteration of these recipes becomes a mini story all its own, with a beginning, a middle and an end. It’s not a coincidence that coders usually use variable names reflecting events in the natural world: birth, death, child, branch, root, etc… The random occurrence of these events gives each of these visual stories its unique character.
In the best of cases, the growing intuition that underlying laws have the potential for infinite manifestations invites contemplation in ways found in classical Islamic art.
The intent of this display is to create a space where, even if you don’t see God, at least you won’t have to run into Clippy.[/vc_column_text][/vc_column][/vc_row]
[vc_row el_class=”th_collection-row” css=”.vc_custom_1615843473810{margin-right: 60px !important;margin-left: 60px !important;}”][vc_column][vc_column_text el_class=”th_collection-title”]Pixel Sculpted Masks, 1989[/vc_column_text][vc_column_text el_class=”th_collection-media”]Scanned Negatives. Amiga Monitor Photos, Digi-Paint.[/vc_column_text][vc_column_text]
Video Datagraphs. iPhone 6, Nuke, Kronos, ffmpeg.
[/vc_column_text][vc_column_text] [/vc_column_text][/vc_column][/vc_row]Binary Clock, Part 2
Atoms, Electrons, PhotonsThe long awaited part 2 of this blog post has finally arrived! Though I’ve been tinkering on this project for the past two years, I decided to write it up to coincide with the outrageous arrest of 14 year old tinkerer Ahmed Mohamed who was hand cuffed because his teacher thought his electronic clock project looked like a bomb. This binary clock project of mine ended up being a personal electronic circuit design introduction course. You can download all the relevant files here if you want to make your own.<br />I forgot what the original inspiration was but what I’m ending up with is a working binary clock on a custom printed circuit board. Ultimately, this project will involve fiber optics inside polished cement for a unique time piece but we’re not there yet… Here’s what I learned so far:
Bit shifters
A binary clock needs 20 individual blinky things and the arduino has less than that, so I needed to figure out a way to create more individually addressable outputs. The solution I found is a the 74HC595N chip that can turn two inputs into 8. In fact, you can wire them in series and they can provide you with any number of outputs in multiples of 8. I decided to use one to drive the hours display, one for the minutes, and one for the seconds.
There are tons of tutorials for them so it was fairly straight forward to get it working.
Keeping time
While you can make a timer with just an arduino, it is not very accurate and it has no way to keep the clock going if you unplug the power. I used a rtc1307 chip which is designed for just this purpose. It keeps time accurately and uses a small battery to continue keeping time when the power is disconnected.
Again, there is an arduino library available and a good amount of tutorials out there so it wasn’t too hard to test it and incorporate it in the build.
Removing the arduino
Eventually, since I wanted to end up with a single circuit board, I didn’t want to have to plug anyting into an arduino. Once again, the internet is a wonderful resource which allowed me to figure out how put only the arduino components I needed onto a bread board. I can upload the code onto the chip by putting it on an arduino, and then pull it off of there to mount it directly onto the breadboard.
Code
The clock can be set to one of 4 modes: display time, set hours, set minutes or set seconds. There are two buttons. One button toggles between all the different modes, while the other increments the count of the hours, minutes, and seconds when they are in their respective mode.
#include <Time.h>
#include <Wire.h>
#include <DS1307RTC.h>
//Pin connected to ST_CP of 74HC595
const int latchPin = 8;
//Pin connected to SH_CP of 74HC595
const int clockPin = 12;
////Pin connected to DS of 74HC595
const int dataPin = 11;
//Pins for setting the time
const int button0Pin = 5;
const int button1Pin = 6;
// Variables for debounce
int button0State;
int button1State;
int previousButton0State = LOW;
int previousButton1State = LOW;
long lastDebounce0Time = 0; // the last time the output pin was toggled
long lastDebounce1Time = 0; // the last time the output pin was toggled
long debounceDelay = 50; // the debounce time; increase if the output flickers
int button0Mode = 0;
// object to communicate with RTC
tmElements_t tm;
void setup() {
// Setup pins for the shift register
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
// Setup pins for manual time setting
pinMode(button0Pin, INPUT);
pinMode(button1Pin, INPUT);
}
void loop() {
RTC.read(tm);
// button 0 can be in display time, hour set, minute set, and second set modes.
//
if( button0Mode == 0){
timeDisplayMode();
}
else if( button0Mode == 1){
setHourMode();
}
else if( button0Mode == 2){
setMinuteMode();
}
else if( button0Mode == 3){
setSecondMode();
}
//
// mode switching
//
// Just after a button is pushed or released, there is noise where the value returned is 0/1 random.
// debouncing consists of reading the incomming value and, if it has changed, storing the time the change was noticed.
// It then continues to check and if after a certain amount of time (delay), it reads the input value and it is still the changed value
// noticed before, then it means that an actual state change happened.
int reading0 = digitalRead(button0Pin);
// this only happens when the input value is different from the last time the value was read
if (reading0 != previousButton0State) {
lastDebounce0Time = millis();
}
// we only enter this loop if the returned value hasn’t changed in a while, which means we are not in the noisy transition
if ((millis() – lastDebounce0Time) > debounceDelay) {
// if we are in here, it means we got two similar readings.
if (reading0 != button0State) {
// if the two similar readings we got are different from the stored state, we must have changed
button0State = reading0;
if(reading0 == HIGH){
button0Mode = (button0Mode+1)%4;
}
}
}
previousButton0State = reading0;
delay(100);
}
void timeDisplayMode(){
int sc = tm.Second;
int mn = tm.Minute;
int hr = tm.Hour;
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, setTimeBits(sc,3));
shiftOut(dataPin, clockPin, MSBFIRST, setTimeBits(mn,3));
shiftOut(dataPin, clockPin, MSBFIRST, setTimeBits(hr,2));
digitalWrite(latchPin, HIGH);
}
void setHourMode(){
int reading1 = digitalRead(button1Pin);
if (reading1 != previousButton1State) {
// reset the debouncing timer
lastDebounce1Time = millis();
}
if ((millis() – lastDebounce1Time) > debounceDelay) {
if (reading1 != button1State) {
button1State = reading1;
if(reading1 == HIGH){
tm.Hour = (tm.Hour+1)%24;
RTC.write(tm);
}
}
}
previousButton1State = reading1;
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, setTimeBits(0,3));
shiftOut(dataPin, clockPin, MSBFIRST, setTimeBits(0,3));
shiftOut(dataPin, clockPin, MSBFIRST, setTimeBits(tm.Hour,2));
digitalWrite(latchPin, HIGH);
}
void setMinuteMode(){
int reading1 = digitalRead(button1Pin);
if (reading1 != previousButton1State) {
// reset the debouncing timer
lastDebounce1Time = millis();
}
if ((millis() – lastDebounce1Time) > debounceDelay) {
if (reading1 != button1State) {
button1State = reading1;
if(reading1 == HIGH){
tm.Minute = (tm.Minute+1)%60;
RTC.write(tm);
}
}
}
previousButton1State = reading1;
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, setTimeBits(0,3));
shiftOut(dataPin, clockPin, MSBFIRST, setTimeBits(tm.Minute,3));
shiftOut(dataPin, clockPin, MSBFIRST, setTimeBits(0,2));
digitalWrite(latchPin, HIGH);
}
void setSecondMode(){
int reading1 = digitalRead(button1Pin);
if (reading1 != previousButton1State) {
// reset the debouncing timer
lastDebounce1Time = millis();
}
if ((millis() – lastDebounce1Time) > debounceDelay) {
if (reading1 != button1State) {
button1State = reading1;
if(reading1 == HIGH){
tm.Second = (tm.Second+1)%60;
RTC.write(tm);
}
}
}
previousButton1State = reading1;
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, setTimeBits(tm.Second,3));
shiftOut(dataPin, clockPin, MSBFIRST, setTimeBits(0,3));
shiftOut(dataPin, clockPin, MSBFIRST, setTimeBits(0,2));
digitalWrite(latchPin, HIGH);
}
// create binary value for each digit of the hour/minute/second number
// offset represents how many bits are used for the tens.
int setTimeBits(int n, int offset){
int n1 = n%10;
int n0 = (n-n1)/10;
return n0 | n1<<offset;
}
Schematic and board
Once the breadboard was working, I set out to sketch the circuit in Fritzing. While it’s not quite as intimidating as EAGLE cad, I ended up using the latter after running into some limitations with the former (I don’t remember what they were). There was a lot for me to learn there but, in the end, it’s conceptually pretty simple: all the pieces have to be connected together correctly. It’s just another way to represent the circuit. Once that was done, I started with the board. I laid out all the components and let the software automatically figure out how to create the correct traces.
One cool thing is that if you choose the correct electronic components in the software, all the size and shapes are properly represented when you are designing the board. It’s a huge pain in the ass to sort through all the libraries of components, though, specially when you don’t know what all the specs mean.
The eagle cad files are included in the download file at the top of this page.
Manufacturing the board
Super simple: just go online and find a service that will manufacture them. For this project, I used oshpark.com and dirtypcbs.com, which allow you to upload your designs right out of EAGLE cad. After a few weeks, you get your board in the mail, ready for you to solder the components on. I order my components from mouser.com, which allows you to save a collection of various components into a project specific list. Again, finding the right components amongst the tens of thousands they have available is really time consuming and annoying. But now, I have my parts list so I never have to go through that again if I want to solder up new versions of the board. The list of parts in included in the download file at the top of this page.
The ugly truth
If you were paying attention, you no doubt noticed in the preceding paragraph that I used two board manufacturers. That is because the first board layouts I had printed actually had shorts. I suppose it’s probably not that uncommon, but it’s really frustrating to upload your designs, order the boards, wait for them to be delivered, spend all this time soldering the board to find out it doesn’t work, and then it can be challenging to figure out where the wires are getting crossed. In the end, I spent about $150 on boards and parts that ended up not working. I guess that’s the cost of learning… My first two board designs were ordered through Oshpark, and the minimum order was 3, for about $50. The third order was done on dirtypcbs and was $25 for 10 boards. They feel cheaper and took forever to get delivered but you sure can’t beat the price.
Flashing Arduino bootloader with Teensy 2.0
ElectronsWhat
If, like me, you want to flash the arduino bootloader onto some blank ATMEGA328 chips on a breadboard and only have a teensy 2.0 on hand (because you’ve short circuited all the working ATMEGA chips you had and so can’t use your arduino), and, unlike me, you don’t have hours to spare trying all freaking possible software/hardware/wiring combination to get it working, here’s what worked for me. Also, since I didn’t want to bother with the crystal, capacitors and resistor, I went for the minimal setup.
Why
Because a chip with the bootloader already loaded costs $5 and a chip without costs $2. And also, really, just because…
How
- I used arduino 1.0.6 on a macbook running osX 10.6 (For those running Yosemite, there are documented issues recognizing the USB port)
- I downloaded Breadboard1-0-x.zip and installed the contained breadboard directory in the “hardware” folder of my sketches.
- In arduino, load the ArduinoISP sketch from the examples, change the LED pin to 11 (#define LED_HB 11), select Teensy 2.0 as you board and upload the sketch
- Wire up the ATMEGA as follows.
- Relaunch arduino and for your board, select Tools > Boards > “ATmega328 on a breadboard (8 MHz internal clock)” and Tools > Programmer > “Arduino as ISP”
- Select Tools > Burn Bootloader
- Done!
- This is basically the steps outlined in the official Arduino website, except for changing the LED pin to 11 in the ArduinoISP sketch and wiring the ATMEGA to the proper pins on the Teensy 2.0. (Note that you don’t even have to change the code to reflect the different pin numbers since they are referred to by their function rather than their number).
There
Here’s a picture and a schematic…
From broken laptop to cool utility monitor
Art, Atoms, ElectronsBroken things are solutions looking for problems. They hold magic undiscovered potential. I hate throwing away broken things because I’m never sure I won’t be able to later re-purpose some part of them into something else. On a seemingly unrelated note, I’m often in need of plugging some random computer or video device in to a screen for testing and, up until now, I have had to swap cables on my desktop monitors or pull out some bulky crappy old monitor from the garage and find some temporary place for it while I use it. What I really want is a small lightweight monitor I can easily access and occasionally plug a Raspberry Pi or my linux server into, something that’s closer in size to a laptop screen than a big bulky desktop monitor and that will not take up desk space.
Cue in broken hardware
As luck would have it, my stupid cat likes to sleep on laptops. They provide a nice warm place and a soothing fan sound. Usually, the only repercussion of this fact is that I sometimes wake up in the morning with hair on the keyboard and the Google helpfully informing me that
In one particular instance however, I was using a hackintoshed Asus 1201N that was clearly not designed to support the weight of a house cat; I know because it never woke up from its night of feline suffocation. I took it apart to see what I could find but never did find the needle in that haystack; probably a shorted motherboard… In the closet of broken stuff it went.
Displays
I’m always thinking about creating different displays. I’m pretty bored with the standard monitor design and I’m always interested in challenges to the rectangle-in-a-sleek-shiny-enclosure status-quo which led me to learn that I could probably find hardware compatible with my broken laptop’s LCD panel. I took the laptop apart, got the part number of the LCD panel and eventually found the right board on ebay for about $30 (I searched for “HSD121PHW1 controller”, HSD121PHW1 being the panel’s model number). Two weeks later, the padded envelope with the telltale Chinese characters on it showed up in my mail mailbox and I immediately plugged it in to test it. Lo and behold, it worked!
From parts to a thing
Okay, so now, I actually have the parts I need to make that small monitor I’ve been wanting: a small LCD panel and a driver board I can plug any HDMI or DVI display into. The next step is putting it together in a cool, cheap and convenient way. I had been peripherally interested by Plexiglas for another project so I decided to try it as a mounting surface for this. I measured the width of the screen and driver board, as well as the height of the screen with and without the adjustment buttons, and got a couple pieces cut at my local plastic store (Santa Monica Plastics). I drilled some holes, mounted the various parts on the back using standoffs, and sandwiched them by screwing in the smaller piece of plexi in the front using longer standoffs.
Binary Clock, Part 1
Art, Electrons
Binary clocks are a family of ubiquitous geek toys which display each digit of the time using binary notation. If you do a search for "binary clock" in Google, you will see a nearly infinite number of implementations. The reason I like the whole genre is that a binary clock is an electronic system that claims to exist for the purpose of conveying information when in fact it's all about finding an obtuse excuse to make something blink. The delight of it is that it's completely impractical to read but the geeks don't care: the coolness of the blinky lights joyfully trumps any need to be practical.
Speaking of geeks, I've been wanting to look into this whole Angular.js framework thingy all those overly bearded tech-hipsters are talking about (when they are not crafting their own cheese or riding fixed wheeled bikes), and so I'm using this blog post as an excuse to program simple apps that illustrate the process I am talking about using Angular.
Displaying numbers in binary
You can see below how to calculate the value a binary number. It's pretty straight forward: a particular place can only be 0 or 1 and once you increment above that, you loop back to 0, add one onto the digit to the left, and if THAT one is already 1, it also loops back to 0 and the behavior ripples leftward.
binary number | {{get8()}} | {{get4()}} | {{get2()}} | {{get1()}} | |||||
x | x | x | x | ||||||
place | 8 | 4 | 2 | 1 | |||||
= | = | = | = | ||||||
total | {{8*get8()}} | + | {{4*get4()}} | + | {{2*get2()}} | + | {{1*get1()}} | = | {{count}} |
Notice that the highest number we can represent a maximum of 16 values with 4 b(inary dig)its. 8 bits can represent 256, 10 bits, 1024, and so on...
Displaying the time in binary
{{d}} |
From math to art
Not comfortable with numbers? Replace the 1's with teale and the 0's with burn sienna, on a background of deep emerald. Bam! Suddenly, you've become an artist, conjuring a playful visual dance of colors on an abstract rhythmic canvas. You're a fucking genius!
{{d}} |
(Note that since the highest number for the hours is 23, the first column never has to go above 2 and we really only need the bottom two places to represent that number. Similarly, the value of minutes and seconds only goes to 59 so the third and fifth columns only to represent the value 5, which can be done with only 3 bits.)
What's next?
Stay tuned... Part 2 describes how to build your very own binary clock, using LED's, chips, electricity, obsession, and patience.