VS1053 Troubleshooting - Fri, 2014-12-12 10:30

Last night, I looked into why Adafruit's VS1053 only works with Teensy 3.1 at 24 MHz, but not 48, 72 or 96 MHz.

Turns out, the library depends SD.begin() to reconfiguring SPI.  It also runs data transfer code from both main program & interrupt context (causing havoc if the interrupt occurs at the wrong moment).  Pretty amazing it's worked on AVR for so long, but apparently it does crash sometimes.  Faster processors increase the opportunity for the problem to strike.

Hopefully my edits from last night will fix these problems for good.


Categories: DorkbotPDX,

Christmas lights notes - Tue, 2014-12-09 22:28

PySerial will tell you that the following baud rates are supported:
(50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000, 2500000, 3000000, 3500000, 4000000)

But it's lies, all lies!!  Well, some lies.  The fact of the matter is that by default the Raspberry Pi baud clock is set to 3 MHz, and the smallest baudrate divisor is 16, leading to a maximum baud rate of 187500, well below our target.  To remedy the situation we need to increase the base clock.  In order to do this, edit /boot/config.txt and add the following line:

init_uart_clock 100000000

100 MHz makes for a nice 2 Mbaud divisor of 50.

Categories: DorkbotPDX,

Improving Arduino's Serial Monitor Performance - Sat, 2014-12-06 20:57

Today I worked on the toughest Arduino bug... keeping the serial monitor from locking up or crashing with maximum speed printing from Teensy 3.1 and Arduino Due.

Here's Technical details and mini rant about Java performance.  Hopefully this (and other good work) will lead to future Arduino versions with a serial monitor that doesn't suck.

Categories: DorkbotPDX,

Strain Relief - Mon, 2014-12-01 00:50

I've struggled with appropriate wire-to-board connections over the years.

Here's one of OMSI's mainstays that I've co-opted that I'd like to share: 

all you do is

Step 1: add a hole in your printed circuit board

Step 2: route the wire through the hole

Step 3: solder the wire to the board

in this case its a 22 gauge wire, 0.1" through hole for strain relief, and a 18 gauge pin hole to solder to.

 Wire is strain releived at the board. Connector is off the board

Shift registers for 64 inputs/outputs and their wires.

Categories: DorkbotPDX,

Six Years of USB Development - Fri, 2014-11-28 13:54

Six years ago, in early Deceber 2008, I left the simple world of serial-based development behind and went native USB, releasing Teensy 1.0.  So much has happened and I've learned a lot in just 6 years.  I used to do everything by 9 pin RS-232 serial ports.  Those days seem so distant.

I'm now working on new and really awesome USB features for 2015...

Categories: DorkbotPDX,

Better SPI Bus Design in 3 Steps - Mon, 2014-11-24 18:11

Most Arduino SPI tutorials show this simple but poor SPI bus design:

A much better SPI bus design can prevent conflicts.  3 simple improvements are needed:

  1. Use pullup resistors on all chip select signals.
  2. Verify tri-state behavior on MISO: use a tri-state buffer chip if necessary.
  3. Protect bus access with SPI.beginTransaction(settings) and SPI.endTransaction().

Click "Read more" for details on these 3 steps.

Step 1: Pullup Resistors for Chip Select & Reset Signals

When multiple SPI devices are used, and especially when each is supported by its own library, pullup resistors are needed on the chip select pins.

Without a pullup resistor, the second device can "hear" and respond to the communication taking place on the first device, if that second device's chip select pin is not pulled up.  This is easy to understand in hindsight, but it can be temendously confusing and frustrating to novice Arduino users who purchase shields or breakout boards without pullup resistors.  Each SPI device works when used alone, but they sometimes mysteriously fail when used together, only because both devices are hearing communication meant to initialize only the first device!

A simpe workaround for devices without pullup resistor involves adding code at the beginning of setup.

void setup() { pinMode(4, OUTPUT); digitalWrite(4, HIGH); pinMode(10, OUTPUT); digitalWrite(10, HIGH); delay(1); // now it's safe to use SD.begin(4) and Ethernet.begin() }


Step 2: Proper MISO Tri-State Behavior

Most SPI chips will tri-state (effectively disconnect) their MISO pin when their chip select signal is high (inactive).

However, some chips do not have proper MISO tri-state behavior.  Fortunately, checking MISO tri-state is easy, especially when prototyping on a breadboard.  Just connect two 10K resistors to the MISO line, like this:

When all SPI chips are disabled, the MISO signal should "float" to approximately half the Vcc voltage.  If any device is still driving the MISO line, you'll see a logic high (usually close to 3.3V or 5.0V) or logic low (close to zero volts).  This test is so easy, it should always be performed by designers of Arduino compatible products.

Arduino shields and breakout boards with poorly-behaved chips should always include a tri-state buffer.  Adafruit's CC3000 breakout board is a good example:


Step 3: USB SPI Transactions in Software

Newer versions of Arduino's SPI library support transactions.  Transactions give you 2 benefits:

  • Your SPI settings are used, even if other devices use different settings
  • Your device gains exclusive use of the SPI bus.  Others will not disturb you.

These improvements solve software conflicts, allowing multiple SPI devices to properly share the SPI bus.

A typical use of transactions looks like this:

SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE0)); digitalWrite(chipSelectPin, LOW); SPI.transfer(mybyte1); SPI.transfer(mybyte2); digitalWrite(chipSelectPin, HIGH); SPI.endTransaction();

SPI.beginTransaction() takes a special SPISettings variable, which give the maximum clock speed, the data order, and clock polarity mode.  The speed is give as an ordinary number, expressing the maximum clock speed that device can use.  The SPI library will automatically select the fastest clock available which is equal or less than your number.  This allows your code to always use the best speed, even on board with different clock speeds.

If your code will ever call SPI library functions from within an interrupt (eg, from attachInterrupt), you must call SPI.usingInterrupt().  For example:

SPI.begin(); SPI.usingInterrupt(digitalPinToInterrupt(mypin)); attachInterrupt(digitalPinToInterrupt(mypin), myFunction, LOW);

If you are developing a library that must be compatible with older versions of Arduino, which lack these SPI transaction functions, you can use SPI_HAS_TRANSACTION to check for the new version.  For example:

#ifdef SPI_HAS_TRANSACTION SPI.beginTransaction(SPISettings(2000000, LSBFIRST, SPI_MODE1)); #endif


Please Share and Use This Information

Today many SPI-based products for Arduino do not work well together.  My hope is this information can help all makers of Arduino compatible devices to achieve much better compatibility.

Long-term, sharing of knowledge is needed.  Please share this information and ask makers of SPI devices and libraries to consider these suggestions.

This article may be shared and copied under the terms of the Creative Commons Attribution 4.0 International License.  Please, copy & share!  :-)



Categories: DorkbotPDX,

[dorkbotpdx-announce] Fwd: Byte Me 4.0 Call for Submissions

dorkbotpdx-announce - Sun, 2014-11-23 12:58
AFRU Gallery has an open call for works for Byte Me 4.0, their annual showcase of technological art. This is a great opportunity to polish up and show off a project you've been working on... Call for works is below: -------- Forwarded Message -------- Subject:         Byte Me 4.0 Call for Submis
Categories: DorkbotPDX, Mailing Lists

Making nRF8001 (Bluetooth LE) and SD cards play nice together - Sun, 2014-11-23 04:30

Been working on making Adafruit_nRF8001 and the SD library work together.  Details are on this forum thread, and also this one.

Categories: DorkbotPDX,


DorkbotPDX Flickr Group - Thu, 2014-11-20 11:16

atduskgreg has added a photo to the pool:


NaNoDrawMo 2014 #36


DorkbotPDX Flickr Group - Thu, 2014-11-20 11:16

atduskgreg has added a photo to the pool:


NaNoDrawMo 2014 #35

This is how we disappear - projection notes - Mon, 2014-11-03 16:03

I’ve been meaning to document my work on this project for about year now. TBA 2014 reminded me it is time to actually do it! So here it is:

For the past year and a half I’ve been working with a dance company called bobbevy. I’ve been creating graphics that go along with the dance performance called “This is how we disappear”. Here’s a review at Portland Monthly.


This is how we disappear - projection edit from Brian Richardson on Vimeo.


More behind the scenes information after the break!

Jesse Meija was doing music and got me involved with this project, I’m very grateful!

Version 1

Effects for the first set of performances:

  • A forest of trees created from a drawings by David Stein.
  • Particle effects that mimiced the dancers movement.
  • Particle effects that just fly across the screen

In order to accomplish this, I wrote a piece of software that would do the animation and handle tracking the dancers. There were two versions, the first version was used to perform a few times. Notably Dance+ in 2012 and as part of Experimental Half Hour XXXVII. It consisted of the following pieces:

  • Cinder, used as a framework
  • Freenect, used to interface to the Microsoft Kinect.
  • Control, used to control the software from an iPad

This version worked ok. Before I started using Control, I had been triggering all of the sequences with keyboard commands. It worked fine, but I had to have a cheatsheet that told me what keys did what. Also, each command just mutated the state of the program, so if you triggered things in a different order you’d end up in different states. This made some rehersals hard, because it was difficult to return the graphics to a previous state. However, with Control, it became easier to use the software. bobbevy performed in Milwaukee without me and was able to use the software just fine! For Dance+ the Kinect refused to work in the studio, I think because the temperature in the room was so high. So I ended up “drawing” the dancers with a multi-touch interface in Control.

For the particle effects that followed the dancers, I ended up using blob tracking and distingugishing blobs based on distance away from the Kinect. I liked the stateless design because the dancers would move in and out of view of the Kinect and I feel that keeping track of them properly would have been a nightmare. This created some surprising benefits though. The swarms move between the dancer when their relationship to the Kinect changes and it created some really nice animations. Also, this piece has a lot of tension between the dancers and the particles ended up expressing some tension when the dancers were about the same distance away from the Kinect.

Version 2

Additional effects for the second set of performances:

  • Static/simple projection mapped screens (similar to my Party House project).
  • Realtime projection mapped patterns on the dancers bodies

This second version of the software was used to perform at NW New Works Festival 2013 and at TBA 2013.

For the second version of the software, I used the following new pieces:

  • QTimeline, this is a timeline that allows one to control tweens of variables
  • QuNeo, as much as I liked Control using a touchscreen while not looking at it (I had to look at the dancers for my cues!) is not ideal. A physical controller allows you to rest you finger on the button/slider you need to push without triggering it. (The cool kids pronounce it keeen-wah).
  • LabMidi, used to interface to the QuNeo
  • For TBA, 3, yes 3! Projectors. Two of them were used to cover the wide background, and one was used to project onto the dancers themselves.

The timeline solved many problems for me. It took what I used to have hard code in the application (fade times, animation speed, etc) and moved it to a data format. The editing GUI was nice to have as well. A new version of Cinder that made using multiple displays easier to use was really nice to have as well. I didn’t need to mirror my desktop screen anymore, which meant I could display debug and other helpful info on my screen. The QuNeo also allowed me to directly control ramp parameters which meant I didn’t need to rely on predetermined fades as much. This also allowed me to be more engaged with the visuals which was really fun. I think the trick to this will be finding the right balance between direct control and triggers to presets. It is probably the same balance electronic musicians search for.

The newest effect for the second run was the projection mapped dancers. In order to accomplish this, I was going to have to find the dancers with the Kinect and then project onto them as close as possible. I used the vvvv patch from here as a starting point to learn how to calibrate my projector with the Kinect. In the end, I wrote my own calibration code because it fit the setup workflow a bit better.

The projection mapped dancers worked pretty well. I was really excited to see them turn into just an indistigushable mass at moments and then turn back into dancers the next. I think this is what projection mapping should do: transform objects and confuse you, then bring you back to reality. I hope to do more of this in the future!

Cross posted from my blog.


Categories: DorkbotPDX,

Windows 10 Preview Build 9860 *finally* fixes USB Serial - Wed, 2014-10-29 16:21

I am happy to report Windows 10 Preview build 9860 fixes the long-standing USB serial bugs, which impact nearly all Arduino compatible boards.

  • The driver loads automatically.  No 3rd party INF is required.
  • The surprise removal bug is finally fixed (was present in build 9841, is fixed in 9860)
  • The seconds-long pause when detecting a new USB device for the very first time appears to be gone.

Windows 10 is finally going to support all class-compliant USB serial (eg, CDC-ACM) as well as Linux and Mac OS-X.  Very exciting.



Categories: DorkbotPDX,

Shall We Dance?

DorkbotPDX Flickr Group - Sat, 2014-09-20 13:59

atduskgreg has added a photo to the pool:

Shall We Dance?

CHURCH OF ROBOTRON - Fri, 2014-09-12 11:28

The Church of Robotron is coming to Portland, OR. We will be open the Last Wednesday of September (the 24th) and the First Thursday of October (the 2nd) starting at 7pm both nights at the Diode Gallery (514 NW Couch St) which is across the street from Ground Kontrol. We'll have multiple versions of Robotron 2084 available to train with and we will be triggering physical events in response to game events. One example: lasers when lasers are shot in game. For info about how this is accomplished, check out this older post.

Right now, we have an installation in the window at the gallery which is running 24/7 until October 3rd. It features a fully playable version of Robtron 2084, sermons, and a leaderboard that has pictures of all who attempt to become the mutant savior. Here's a video of it:

The window sensor is a capacitive sensor that was made by Philip Odom. He used the same techniques he taught during the Capacitive Sensing Workshop. Jason Plumb got audio working by using a transducer that turns the window into a speaker. The sign was built by Debbie Wager. Finally, this was all integrated together by the rest of the church.

Come check out the window anytime! Come to our open nights (9/24 & 10/2), check out this post for an idea of what to expect!

Categories: DorkbotPDX,

Embrace Heart Lighting - Wed, 2014-09-03 03:02

Earlier this summer, I worked on a tiny piece of the Embrace sculpture, for Burning Man 2014.

Inside were 2 hearts, one made here in Portland by Lostmachine Andy & other burners at Flat Rat Studios.  I made electronics to gradually fade 4 incandescent light bulbs in heart beating patterns.

Click "Read more" for technical details and many more wonderful photos (taken by Sarah Taylor)....

Inside the enormous sculpture were two hearts.  The blue on was built by a group in Vancouver, B.C., Canada, and of course this one was built here in Portland, Oregon, USA.

Andy wanted this heart to have a very warm, gentle atmosphere, with warn incandescent bulbs slowly fading to create the heart beat.  These effect turned out quite well.

Here's a quick video, from the first test of the light controller.

The electronics all fit onto this circuit board, which is approximately 4 by 3.5 inches.

The four BT139X Triacs that actually switch the AC voltage are mounted on the bottom side to a heatsink that's meant to dissipate any heat to the metal case.  Originally Andy believed the lights might be 500 watts each, so I was concerned about heat.  In the end, four 60 watt bulbs were used and the Triacs did not get noticeably warm.

Here is a parts placement diagram for building the circuit board.  Two boards were built, the one that ran the project and a spare... just in case!

The PCB cad files are attached below, if anyone wants to make more of these boards.

The AC switching circuitry was basically Fairchild Semiconductor's recommended circuit for the MOC3023 optical isolator, which allows a Teensy 2.0 board to safely control the AC voltage.  Four copies of this circuit were built on the board.

This circuit requires the Teensy 2.0 to know the AC voltage timing, so it can trigger the Triac at the right moment.  Triggering early in the AC waveform causes the Triac to conduct near the full AC voltage for maximum brightness.  Triggering later reduces the brightness.

To get the AC timing, I built this special power supply onto the board.

The Teensy 2.0 receives pulses on pins 5 and 6 as the AC waveform cycles positive and negative.

One caveat is this approach depends on the AC voltage being a sine wave.  The AC voltage was one of the first questions I asked Andy, and he was told Burning Man would supply a true sine wave AC voltage.  When he got out there, it turned out the power was actually a "modified sine wave", which really isn't anything like a sine wave.  This circuit didn't work well.  Fortunately, they were able to run the lighting from a small generator that produced a true sine wave.

With the AC timing arriving on pins 5 and 6, and 4 pins able to trigger Triacs, and 3 pins connected to analog voltages for changing speed, brightness and pattern, the only other major piece of this technology puzzle is the software.

In this code, loop() tracks the changes in the waveform on pins 5 & 6, and it fires the Triacs at their programmed times.  120 times per second (each AC half cycle), the recompute_levels() function runs, which reads the analog controls and changes the Triac time targets, which loop() uses to actually control the voltage outputs.

Here's all the code:


void setup() { pinMode(0, INPUT_PULLUP); // unused pinMode(1, INPUT_PULLUP); // unused pinMode(2, INPUT_PULLUP); // unused pinMode(3, INPUT_PULLUP); // unused pinMode(4, INPUT_PULLUP); // unused pinMode(5, INPUT); // Phase A pinMode(6, INPUT); // Phase B pinMode(7, INPUT_PULLUP); // unused pinMode(8, INPUT_PULLUP); // unused pinMode(9, INPUT_PULLUP); // unused pinMode(10, INPUT_PULLUP); // unused digitalWrite(11, LOW); pinMode(11, OUTPUT); // LED digitalWrite(12, HIGH); pinMode(12, OUTPUT); // trigger4, low=trigger digitalWrite(13, HIGH); pinMode(13, OUTPUT); // trigger3, low=trigger digitalWrite(14, HIGH); pinMode(14, OUTPUT); // trigger2, low=trigger digitalWrite(15, HIGH); pinMode(15, OUTPUT); // trigger1, low=trigger pinMode(16, INPUT_PULLUP); // unused pinMode(17, INPUT_PULLUP); // unused pinMode(18, INPUT_PULLUP); // unused analogRead(19); // pot #3 analogRead(20); // pot #2 analogRead(21); // pot #1 pinMode(22, INPUT_PULLUP); // unused pinMode(23, INPUT_PULLUP); // unused pinMode(24, INPUT_PULLUP); // unused } uint8_t pot1=0, pot2=0, pot3=0; uint8_t level1=100, level2=128, level3=0, level4=250; uint8_t phase_to_level(uint16_t phase) { uint16_t amplitude; // 10923 = 32768 / 3 // 0 to 10922 = increasing: 0 -> 32767 // 10923 to 21845 = decreasing: 32767 -> 0 // 21846 to 32768 = increasing: 0 -> 32767 // 32769 to 43691 = decreasing: 32767 -> 0 // 43692 to 65535 = resting: 0 if (phase < 10923) { amplitude = phase * 3; } else if (phase < 21845) { phase = phase - 10923; phase = 10922 - phase; amplitude = phase * 3; } else if (phase < 32768) { phase = phase - 21846; amplitude = phase * 3; } else if (phase < 43691) { phase = phase - 32769; phase = 10922 - phase; amplitude = phase * 3; } else { amplitude = 0; } //amplitude = (phase < 32768) ? phase : 65535 - phase; amplitude >>= 6; // range 0 to 511 amplitude *= (pot2 + 84) / 6; // amplitude += 6000 + pot2 * 8; // minimum brightness return (amplitude < 32768) ? amplitude >> 7 : 255; } void recompute_levels() { static uint16_t phase=0; static uint8_t n=0; analog_update(); //Serial.print("pot: "); //Serial.print(pot1); //Serial.print(", "); //Serial.print(pot2); //Serial.print(", "); //Serial.print(pot3); phase += (((uint16_t)pot1 * 83) >> 5) + 170; //Serial.print(", phase: "); //Serial.print(phase); if (pot3 < 128) { level1 = phase_to_level(phase); level2 = level1; level3 = phase_to_level(phase + pot3 * 52); level4 = level3; } else { uint16_t n = (pot3 - 127) * 26; level1 = phase_to_level(phase); level2 = phase_to_level(phase + 6604 - n); level3 = phase_to_level(phase + 6604); level4 = phase_to_level(phase + 6604 + n); } //Serial.print(", levels: "); //Serial.print(level1); //Serial.print(", "); //Serial.print(level2); //Serial.print(", "); //Serial.print(level3); //Serial.print(", "); //Serial.print(level4); //Serial.println(); } void loop() { uint8_t a, b, prev_a=0, prev_b=0, state=255, triggered=0; uint32_t usec, abegin, bbegin, alen, blen; uint16_t atrig1, atrig2, atrig3, atrig4; uint16_t btrig1, btrig2, btrig3, btrig4; bool any; while (1) { // read the phase voltage and keep track of AC waveform timing a = digitalRead(5); b = digitalRead(6); if (a && !prev_a) { // begin phase A usec = micros(); if (state == 0) { state = 1; abegin = usec; triggered = 0; Serial.print("A"); Serial.println(usec); } else if (state == 255) { state = 11; abegin = usec; } else { state = 255; } } if (!a && prev_a) { // end phase A usec = micros(); if (state == 1) { state = 2; alen = usec - abegin; Serial.print("a"); Serial.print(usec); Serial.print(","); Serial.println(alen); if (alen < 12000) { // compute trigger offsets for next A phase recompute_levels(); atrig1 = level1 ? ((256 - level1) * alen) >> 8 : 30000; atrig2 = level2 ? ((256 - level2) * alen) >> 8 : 30000; atrig3 = level3 ? ((256 - level3) * alen) >> 8 : 30000; atrig4 = level4 ? ((256 - level4) * alen) >> 8 : 30000; } else { state = 255; } } else if (state == 11) { state = 12; alen = usec - abegin; } else { state = 255; } } if (b && !prev_b) { // begin phase B usec = micros(); if (state == 2) { state = 3; bbegin = usec; triggered = 0; Serial.print("B"); Serial.println(usec); } else if (state == 12) { state = 13; bbegin = usec; } else { state = 255; } } if (!b && prev_b) { // end phase B usec = micros(); if (state == 3) { state = 0; blen = usec - bbegin; Serial.print("b"); Serial.print(usec); Serial.print(","); Serial.println(blen); if (blen < 12000) { // compute trigger offsets for next B phase recompute_levels(); btrig1 = level1 ? ((256 - level1) * blen) >> 8 : 30000; btrig2 = level2 ? ((256 - level2) * blen) >> 8 : 30000; btrig3 = level3 ? ((256 - level3) * blen) >> 8 : 30000; btrig4 = level4 ? ((256 - level4) * blen) >> 8 : 30000; } else { state = 255; } } else if (state == 13) { state = 0; blen = usec - bbegin; } else { state = 255; } } prev_a = a; prev_b = b; // trigger triacs at the right moments if (state == 1) { usec = micros(); any = false; if (!(triggered & 1) && usec - abegin >= atrig1) { digitalWrite(15, LOW); triggered |= 1; any = true; //Serial.println("trig1(a)"); } if (!(triggered & 2) && usec - abegin >= atrig2) { digitalWrite(14, LOW); triggered |= 2; any = true; //Serial.println("trig2(a)"); } if (!(triggered & 4) && usec - abegin >= atrig3) { digitalWrite(13, LOW); triggered |= 4; any = true; //Serial.println("trig3(a)"); } if (!(triggered & 8) && usec - abegin >= atrig4) { digitalWrite(12, LOW); triggered |= 8; any = true; //Serial.println("trig4(a)"); } if (any) { delayMicroseconds(25); digitalWrite(15, HIGH); digitalWrite(14, HIGH); digitalWrite(13, HIGH); digitalWrite(12, HIGH); } } else if (state == 3) { usec = micros(); any = false; if (!(triggered & 1) && usec - bbegin >= btrig1) { digitalWrite(15, LOW); triggered |= 1; any = true; //Serial.println("trig1(b)"); } if (!(triggered & 2) && usec - bbegin >= btrig2) { digitalWrite(14, LOW); triggered |= 2; any = true; //Serial.println("trig2(b)"); } if (!(triggered & 4) && usec - bbegin >= btrig3) { digitalWrite(13, LOW); triggered |= 4; any = true; //Serial.println("trig3(b)"); } if (!(triggered & 8) && usec - bbegin >= btrig4) { digitalWrite(12, LOW); triggered |= 8; any = true; //Serial.println("trig4(b)"); } if (any) { delayMicroseconds(25); digitalWrite(15, HIGH); digitalWrite(14, HIGH); digitalWrite(13, HIGH); digitalWrite(12, HIGH); } } } } #define ADMUX_POT1  0x60 #define ADMUX_POT2  0x61 #define ADMUX_POT3  0x64 void analog_update() { static uint8_t count=0; switch (count) {   case 0: // start conversion on pot #1 ADMUX = ADMUX_POT1; ADCSRA |= (1<<ADSC); count = 1; return;   case 1: // read conversion on pot #1 if (ADCSRA & (1<<ADSC)) return; pot1 = ADCH; ADMUX = ADMUX_POT2; count = 2; return;   case 2: // start conversion on pot #2 ADMUX = ADMUX_POT2; ADCSRA |= (1<<ADSC); count = 3; return;   case 3: // read conversion on pot #2 if (ADCSRA & (1<<ADSC)) return; pot2 = ADCH; ADMUX = ADMUX_POT3; count = 4; return;   case 4: // start conversion on pot #3 ADMUX = ADMUX_POT3; ADCSRA |= (1<<ADSC); count = 5; return;   case 5: // read conversion on pot #3 if (ADCSRA & (1<<ADSC)) return; pot3 = ADCH; ADMUX = ADMUX_POT1; count = 0; return;   default: count = 0; } }

Update: Here's a great time-lapse video where you can see the slow, gradual incandescent light fading as a rapid heart beat.  Skip forward to about 0:36 to see it quickly.




AttachmentSize embraceheart_pcb_files.zip18.06 KB
Categories: DorkbotPDX,

Re: [dorkbotpdx-blabber] OSHPark is hiring - Board depaneler

dorkbotpdx-discuss - Thu, 2013-06-20 12:00
DOH! I did it too... Please ignore my previous post, it was ment to be sent
directly to James...


On Tue, Jun 18, 2013 at 12:07 PM, Jason Barnett

Categories: DorkbotPDX, Mailing Lists

Re: [dorkbotpdx-blabber] OSHPark is hiring - Board depaneler

dorkbotpdx-discuss - Thu, 2013-06-20 12:00
I mentioned this job to my wife, Nobuko, and she is interested in it. She
came with me from Japan and thus has no work history since we came to the
states and is trying to get back into the workforce. She is now a US
citizen so will have no problem with that aspect of employment.
While living in Japan, she worked as a receptionist for a respected lawyer
Categories: DorkbotPDX, Mailing Lists

Re: [dorkbotpdx-blabber] Anyone with CAN experience?

dorkbotpdx-discuss - Thu, 2013-06-20 12:00
Thanks! The Smartboard has Ethernet already. I could use just about any
wifi router/bridge to connect the device through Wifi. It's an option that
I'm definitely considering.

______________________________ _________________
dorkbotpdx-blabber mailing list

Categories: DorkbotPDX, Mailing Lists

Re: [dorkbotpdx-blabber] Anyone with CAN experience?

dorkbotpdx-discuss - Thu, 2013-06-20 12:00
whoops, here's the product

______________________________ _________________
dorkbotpdx-blabber mailing list

Categories: DorkbotPDX, Mailing Lists

Re: [dorkbotpdx-blabber] Anyone with CAN experience?

dorkbotpdx-discuss - Thu, 2013-06-20 12:00
If you don't need it to be going out via bluetooth and can tolerate
wifi, this is around $25-30 and has a UART port on it, so you could
interface it with your smartboard to send out the data that way. This
driver file says:


Categories: DorkbotPDX, Mailing Lists
Syndicate content