Advertisements

Archive for April, 2018

Roadside Debris: Cannabis Energy Drink

Spotted this on Rt 376 during a ride around the block:

Cannabis Energy Drink - roadside debris

Cannabis Energy Drink – roadside debris

A “Cannabis Energy Drink” without the obvious active ingredient seems like deceptive marketing to me, but, apparently, there was no law against that, even here in New York State.

It’s becoming obvious I don’t get out nearly enough.

Advertisements

2 Comments

Pixel XL Camera vs. Barred Owl

A pair of barred owls have been doing call-response “Who cooks for you” chants during the late afternoon, we finally spotted one, and I have a Pixel XL in my pocket:

Barred owl - overview

Barred owl – overview

That’s with the camera zoomed all the way, so it’s blowing up the raw pixels by a factor of four. Cropping out the middle and resizing by 300% shows the result doesn’t have much detail:

Barred owl - zoomed 3x cropped

Barred owl – zoomed 3x cropped

We snagged the binoculars on the way out the door, so we got a better look than you do. The camera you have is much better than the camera you don’t, but big glass always wins over tiny optics!

Leave a comment

Mouse Fatality

It seems the rodents around here have lost their fear of enclosed spaces:

Drowned mouse

Drowned mouse

I cannot be bothered to conjure a mesh lid for the bowl, though.

1 Comment

Streaming Radio Player: Continued Glitchiness

The SPI OLEDs continue to misbehave, with this early morning glitch jamming the display into a complete lockup:

RPi OLED display - left-edge garble

RPi OLED display – left-edge garble

A normal, albeit blind, shutdown-and-reset brought it back to life.

Other OLEDs on other RPis have occasionally misbehaved since the most recent (attempted) tweak, so it hasn’t made any difference.

One obvious lesson: prefer OLEDs with I2C interfaces.

Leave a comment

Teensy 3.6 USB Serial Startup

The Arduino Serial doc says the USB hardware on the (now obsolescent) Leonardo requires a test-for-open before using the serial port:

  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB
  }
}

As it happens, you must also use that test on the ARM-based Teensy 3.6.

The gotcha happens when the USB port doesn’t become available, in which case the conditional remains true and the loop continues forever, which is precisely what happened when I powered the Teensy from a USB battery pack on the Squidwrench Operating Table.

After some flailing around, this startup snippet falls through after ahem awhile:

#define BUILTIN_LED 13

... snippage ...

Serial.begin(115200);

int waited = 0;
while (!Serial && waited < 3000) {
  delay(1);
  waited++;
  if (! (waited % 50))
    FlipPin(BUILTIN_LED);
}

... snippage ...

Serial.printf(" serial wait: %d ms\n\n",waited);

The serial startup delay seems to vary unpredictably between 800 and 1800 ms, so 3000 ms may be too short:

serial wait: 1033 ms
serial wait: 899 ms
serial wait: 907 ms

The ARM Teensy connects the board's built-in LED to the same SPI clock as on the AVR Arduinos, so it's only useful during startup, but having some hint will come in handy the next time it jams for another reason.

,

3 Comments

FM DDS: SPI Mock 2

Doing the DDS calculations in full-frontal double floating point turns out to be maybe fast enough:

DDS Mock - 0 VAC - SPI

DDS Mock – 0 VAC – SPI

I set the ADC to HIGH_SPEED conversion and sampling, reducing the time between the start of conversion (first pulse in D1) and the ADC end-of-conversion interrupt (rising edge in D2) from 4.7 μs to 2.6 μs, more-or-less, kinda-sorta.

The ADC hardware can return the average of several sample taken in quick succession, so I set it to average four samples. The vertical cursors show the combination of fast conversion and averaging requires 7 μs (-ish) from start to finish: long enough to justify separating the two by an interrupt and short enough to allow calculations after fetching the result.

The purple trace shows the analog input voltage hovering close to a constant VCC/2 (about 1.6+ V), rather than the sine-wave I used earlier, again courtesy of the scope’s arbitrary function generator. The loop() dumps the min and max ADC values (minus half the ADC range (4096/2= 2048):

    -4 to     2
    -3 to     2
    -3 to     2

A span of half a dozen counts = 3 bits means the 12 bit ADC really delivers 9 bits = 0.2% resolution = 54 dB dynamic range = probably not good enough. However, the “circuit” is an open-air hairball on the bench, driven from the scope’s arbitrary waveform generator in high-Z mode, so things can only get better with more any attention to detail.

The 1.9 μs gap between the first and second burst of SPI clocks contains all the floating-point calculations required to convert an ADC sample to DDS delta-phase bits:

void adc0_isr(void) {

  int Audio;

  digitalWriteFast(PIN_ANALOG,HIGH);

  AnalogSample = adc->readSingle();             	  // fetch just-finished sample
  Audio = AnalogSample - 2048;                      // convert to AC signal

  DDSBuffer.Phase = 0;

  SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
  digitalWriteFast(PIN_DDS_FQUD, LOW);

  SPI.transfer(DDSBuffer.Phase);

  DDSBuffer.DeltaPhase = (uint32_t)((((double)Audio / 2048.0) * Deviation + Crystal) * CountPerHertz);

  SPI.transfer((uint8_t)(DDSBuffer.DeltaPhase >> 24));      // MSB first!

  if (Audio > AudioMax)                                     // ignore race conditions
    AudioMax = Audio;
  if (Audio < AudioMin) AudioMin = Audio; SPI.transfer((uint8_t)(DDSBuffer.DeltaPhase >> 16));

  SPI.transfer((uint8_t)(DDSBuffer.DeltaPhase >>  8));
  SPI.transfer((uint8_t)DDSBuffer.DeltaPhase);

  SPI.endTransaction();                         // do not raise FQ_UD until next timer tick!

  digitalWriteFast(PIN_ANALOG,LOW);
}

A closer look lets the scope decode and present the SPI data:

DDS Mock - 0 VAC - SPI detail

DDS Mock – 0 VAC – SPI detail

The program calculates and displays various “constants” I set for convenience:

FM Modulated DDS
Ed Nisley KE4ZNU
 serial wait: 890 ms

DDS clock:     180000000.000 Hz
CountPerHertz:        23.861 ct
HertzPerCount:         0.042 Hz

Crystal:    20000000.000 Hz
Deviation:      5000.000 Hz

You can confirm the SPI data by working backwards with a calculator:

  • DDS delta-phase register bytes: 1C 71 C6 E2 = 477218530 decimal
  • Multiply by 180 MHz / 2^32 to get frequency: 1999997.5506 Hz
  • Subtract nominal 20.0 MHz crystal to get modulation: -2.4494 Hz
  • Divide by nominal 5.0 kHz deviation to get fractional modulation: -4.89.9e-6
  • Multiply by half the ADC range (4096/2) to get ADC counts: -1.003
  • Add 2048 to get the actual ADC sample: 2047

Nicely inside the range of values reported by the main loop, whew.

Which means I can avoid screwing around with fixed-point arithmetic until such time as clawing back a few microseconds makes a meaningful difference.

Now, to begin paying attention to those pesky hardware details …

The TeensyDuino source code as a GitHub Gist:

Leave a comment

Mis-Punched Scope Probe Hook

Back in the day, HP scope probes had a rugged music-wire hook on the tip:

HP scope probe tip

HP scope probe tip

These days, scope probe tips use ordinary sheet steel punched into a hook shape:

Siglent scope probe - good tip

Siglent scope probe – good tip

By sheer bad luck, the first probe out of the bag had a mis-punched end with no griptivity:

Siglent scope probe - mis-cut tip

Siglent scope probe – mis-cut tip

Dunno what happened, but it was definitely sheared off in the factory.

After I finally recognized the problem, I shaped a crude hook with a safe-edge needle file and continued the mission:

Siglent scope probe - filed tip

Siglent scope probe – filed tip

A quick note to Siglent put a replacement probe tip in the mail, so it’s all good.

2 Comments