Raspberry Pi Character LCD Degree Symbol

It is inevitable that you will want to write the degree symbol to your 16×2 character LCD once you have it wired to the Pi. My son wired it up, and then wanted to display the degree symbol. In the past I have solved that problem for the Arduino using the Adafruit character LCD Arduino library createChar() function. Relatively painless for the Arduino. Unfortunately, the Adafruit LCD library for GPIO not using i2c does not have an equivalent of the createChar() function. Sad.

The solution turns out to be easy. You rely on the fact that the LCD already has a degree symbol built in, and then use the write4bits() function to display it. There are other characters available, I found mine here. Here is our code.
[code language=”python”]
# This is the process of importing the Adafruit library
adafruitCharLCDPath = "/home/pi/pylib/AdafruitPy/Adafruit_CharLCD"
if not adafruitCharLCDPath in sys.path:
sys.path.append( adafruitCharLCDPath)
from Adafruit_CharLCD import Adafruit_CharLCD

os.system(‘modprobe w1-gpio’)
os.system(‘modprobe w1-therm’)

temp_c = 23.1
temp_f = 32. + temp_c*9./5.

lcd = Adafruit_CharLCD()
lcd.message("temp C")
lcd.write4bits( 0xDF, True)
lcd.message(": %.1fn"%temp_c)

lcd.message("temp F")
lcd.write4bits( 0xDF, True)
lcd.message(": %.1f"%temp_f)



That Noisy Fan–Calibrated Measurement

I am working with the freetronics microphone module, which is described as having a sensitivity of “-40 dB typical”—let us assume it is dB (SPL) referenced to 20 micropascals root mean square (rms) at 1 KHz. When I think of an electronic element’s sensitivity, though, I’m thinking volts per micropascal and this is not provided.

The microphone’s schematic suggests the SPL measurement is the rms average over 3 milliseconds, and that the signal is proportional to rms pressure level. This suggests a log scale for display (a change from previous work).

The upshot is that the fan generates about 62 dBA; but to get that conclusion, I had to perform a spectral correction to match measurements from a more calibrated sensor.


Remember that I made the measurements with the RIMU data logger I built. That data logger has a digital low-pass filter on the microphone SPL. The low-pass filter has much too slow a response, but the basic result is OK. The RIMU, shown in the next picture, is the instrument.


I borrowed an SPL meter from my father (thanks!). It is, unfortunately, a C-weighted measurement, measuring in dBC. The C-weighting is occasionally a very useful measurement of sound level. Most measurements are done A-weighted, which is similar to human hearing. My challenge is to convert a measurement made with an unweighted microphone in arbitrary units to A-weighted measurement in dBA. The answer is to take a measurement with the instrument in dBC, and record the sound a with a sound recorder, figure out what converts C-weighting to A-weighting for this signal.


In the spectra below you can see that the spectrum recorded without weighting, by the Zoom recorder. I then applied an A weighting and a C weighting. What’s important is the conversion between the rms value for A and the rms value for C, which is a 6 dB correction in one case, and a 13 dB correction in the other.




So, to rehash the steps

  • Record a sound level with the RIMU
  • Measure a reference condition in dBC with the SPL
  • Record a 15 second period with the Zoom
  • Apply the A weighting to the Zoom record
  • Apply the C weighting to the Zoom record
  • Find the difference in dB between the A and C weighted records
  • Assume the dBC weighting corresponds to the measurement made with the RIMU, and adjust the RIMU values so that they match the C-weighted measurement from the SPL
  • Apply the C-to-A correction to the RIMU measurement.

Pretty epic pain, but at least I have the measurements. In the future I will recode the RIMU to take short A-weighted and C-weighted snapshots, and then calibrate the RIMU on the dBA record. Look for a follow-up post far in the future.

Arduino Analog Sample Rate

The Arduino Uno is not the ultimate signal processing machine, but it can do some light duty work on burst data. I had trouble finding the maximum sample rate the Uno can support, which is totally critical for most kinds of work.

With native prescale

  • Samples, type casts into floats, and stores in an array at about 8929 Hz, or 112 microseconds per read-and-store
  • Samples and into stores into an array of unsigned integers (16 bit) at about 8930 Hz, or 112 microseconds per read-and-store

We can step this up quite dramatically by setting the prescale set to 16:

  • Samples, type casts into floats, and stores in an array at about 58600 Hz, or 17 microseconds per read-and-store
  • Samples and stores into an array of unsigned integers (16 bit) at about 58606 Hz, or 17 microseconds per read-and-store

Pretty close to a 60 KHz sample rate, more than adequate for audio sampling. Of course, the Arduino doesn’t have enough memory to be a serious audio processor, but it is pretty goood.

The forums discuss this, and arrive at a similar conclusion.

[code language=”c”]
#define NSAMP 5000

void setup(){
Serial.begin( 57600);

float array_float[ NSAMP]; // float
unsigned int array_int[ NSAMP]; // 16 bit
unsigned long int micsbegf, micsendf, micsbegi, micsendi;

for( int i = 0; i < 2; i++){
if ( i == 1){
// Set prescale to 16, and retry

// Record floats (extra time for type conversion presumably)
micsbegf = micros();
for( int i = 1; i < NSAMP; i++){
array_float[ i] = (float)analogRead( A1);
micsendf = micros();

// Record floats (extra time for type conversion presumably)
micsbegi = micros();
for( int i = 1; i < NSAMP; i++){
array_int[ i] = analogRead( A1);
micsendi = micros();

if( i == 1){
Serial.println("with prescale set to 16");
Serial.print("recorded ");
Serial.print( NSAMP);
Serial.print(" float samples in ");
Serial.print(micsendf – micsbegf);
Serial.println(" usec");

Serial.print("recorded ");
Serial.print( NSAMP);
Serial.print(" unsigned integer samples in ");
Serial.print(micsendi – micsbegi);
Serial.println(" usec");

void loop(){
delay( 10);