Tuesday, 23 June 2015

Simple nodemcu module to drive a nokia LCD (PCD8544)

I desperately wanted to hook a Nokia5110 LCD to my nodemcu. I wrote a LUA module but it was slow and it was taking too much memory, mainly because the font data needs to stay in the precious RAM.

It looks like anything I do ends up taking too much memory, so the way to go is to write modules in c and then invoke them from LUA. I am very pleased with the results, so here it is for you to use: Download (just for fun the lua module and the image are also included)

You can use it this way:
  • pcd.init()
  • pcd.locate(0,0)
  • pcd.print("Hello world!")
And if you want to display images you can do it this way:
  • pcd.init() 
  • file.open("image.bin", "r") 
  • pcd.printbin(file.read()) 
  • file.close()
I already sent a pullrequest to the nodemcu guys, it may not get accepted as the pins needed are hardcoded :/ 

Saturday, 5 October 2013

Software defined FM radio transmitter (Arduino + AD9850)

This video shows it all, take it away!

The frequency is generated by the AD9850 and the modulation is done by the arduino

The full code is here:

The FM band channels are centered at certain frequency, in our case 90Mhz, any slight deviation of that freq (by a max of +/- 75Khz) will move the membrane of the speaker backward or forward, here is the bit of code that implements that. And this is the (unoptimized) modulation routine.
void playTone(unsigned int note, unsigned int duration ) 
  const double freq = 90 * 1e6; // transmitting at 90Mhz

  // play silence 
  if ( note == 0)
  unsigned long currentMillis = millis() + duration;
  while( millis()< currentMillis)
      ad.setfreq(freq + 75e3/2); // speaker's membrane backward
      ad.setfreq(freq - 75e3/2); // speaker's membrane forward

  ad.setfreq(freq );

Credits go to:
Brett Hagman for the RTTTL tune player
Poul-Henning Kamp for the AD9850 lib

Friday, 5 July 2013

Minimal ECG using an Arduino and Xoscillo

First off, the picture :)

To display the wave I am using XOSCILLO, a very cool and open source tool (which I wrote :P) that converts your Arduino into an oscilloscope.

Circuit diagram

Here is the scheme, I am using the typical instrumental amplifier(ins amp) and then another op amp to get some more gain. An ins-amp is like an op-amps but with a huge CMRR, I am using a AD8221 which comes in a tiny small package, it's lead pitch is only 0.65mm, if you want to know what I did to create a simple breakout board please follow this link.

I'm using a single supply for the amps that comes from the arduino 5V pin, and I am creating a buffered virtual ground, this is really important.

Here is, a bit dark, a pic of the setup in the breadboard.

Tricks of the trade:

This is what makes the difference between a working ECG and a non working one :)

The main problem is that the device is so sensitive that it get interference from almost everywhere, specially the mains hum at 50hz). As you can see I got a clean signal, and I am not using any kind of serious filtering, note that xoscillo has a low pass filter and I am not even using it, so what are the tricks?

  1. Run it from a laptop and unplug the charger!
  2. Don't use a second monitor, the HDMI port will cause all sorts of high frequency interferences
  3. Get about 1 meter away from the laptop
  4. Buy some serious ECG electrodes, mines are "H124SG * Ø 24 mm", they come in a box of 50 and should cost about 11 euros. 

That's all, if you like it or build it or need help feel free to write a comment, it will encourage me to write more articles :)

Saturday, 22 June 2013

Poor man's MSOP soldering

MSOP stands for Mini Small  Outline Package, that means that width of 4 leads is just 2mm, exactly the width of a row in a stripboard... Let see how can we solder that though.

On a piece of wood we tape carefully 4 thin wires. We start my taping one wire and then taping again a second one at a distance of 2mm, take as much time as you need, this step is crucial, place on top the MSOP to make sure they have the right separation. If you need to make any adjustments use the blade of a cutter to move the wire. Good now you have the top one and the lower one. For the 2 inner ones, just put them in between and fix them with tape, then use the cutter blade to make sure they are all spaced equally

We place the MSOP on top and we tape it, then make the necessary adjustments in the separations of the wires. Once we are happy we tape the IC this time more tightly.
 Time to solder, use flux and apply the iron firmly as with any other SMD
Once we have one side done we do the other side, this time it will be easier since the other half is firmly fixed, time to correct the separation of the wires too.
 Once we remove the tape we check the back of the IC to make sure all looks good and clean.
 We cut the thin wires by just applying some firm vertical pressure with a cutter.

 Time to  place it on the stripboard, we carefully separate the wires and we insert them through the holes,
 And voila, the breakout board :)

Tuesday, 26 February 2013

Measuring inductances using an arduino

I just read this excellent article about measuring inductances:


The technique consists in measuring the resonance frequency of a LC circuit. Since this frequency is:

f = 1.0/(2.0*M_PI*sqrt(L*C))

By measuring f with the arduino and knowing C you can easily get L.

I modified the code so its much more precise, the original code is using 'pulse' to read half an oscillation. My code instead measures one whole oscillation by using an AVR's hw feature called Input Compare, this feaure starts and stops a timer that runs at 16Mhz.


//measuring inductance using the higher precision input compare  
//based on http://reibot.org/2011/07/19/measuring-inductance/  
//capture Flag  
volatile uint8_t Flag;
void InitTimer1(void)
    //Set Initial Timer value  
    TCCR1A = 0;
    TCCR1B = 0;
    // Input Capture Noise Canceller  
    TCCR1B |= (1 << ICNC1);
    //First capture on rising edge  
    TCCR1B |= (1 << ICES1);
    //Start timer without prescaller  
    TCCR1B &= ~ ((1 << CS12) | (1 << CS11) | (1 << CS10));
    TCCR1B |= (1 << CS10);
    //Enable input capture and overflow interrupts  
    TIMSK1 = 0;
    TIMSK1 |= (1 << ICIE1) | (1 << TOIE1);
    Flag = 0;
volatile uint16_t Capt;
volatile uint16_t T1Ovs2;
//capture ISR  
    if (Flag == 0)
        //reset overflows  
        TCNT1 = 0;
        T1Ovs2 = 0;
    else if (Flag == 1)
        Capt = ICR1;
        //disable capture and overflow interrupts
        TIMSK1 &= ~ ((1 << ICIE1) | (1 << TOIE1));
        //clear pending interrupts  
        TIFR1 = (1 << ICF1) | (1 << TOV1);
    //increment Flag  
//Overflow ISR  
    T1Ovs2++; //increment overflow counter  
//13 is the input to the circuit (connects to 150ohm resistor)
//8 is the comparator/op-amp output.   
//reibot.org for guide  
double pulse, freq, inductance;
//insert capacitance here. Currently using 2uF  
double capacitance = 2E-6;
void setup()
    pinMode(8, INPUT);
    digitalWrite(8, LOW);
    pinMode(13, OUTPUT);
    Serial.println("Why hello!");
void loop()
    digitalWrite(13, HIGH);
    delay(10); //give some time to charge inductor.   
    digitalWrite(13, LOW);
    delayMicroseconds(15); //make sure resonance is measured  
    delay(100); // wait for ICR to read once cycle  
    pulse = (T1Ovs2 * 65536 + Capt) / 16.0;
    if (pulse > 0.1)
        freq = 1.E6 / pulse;
        inductance = 1. / (capacitance * freq * freq * 4. * 3.14159 * 3.14159);
        inductance *= 1E6;
        Serial.print("High for uS:");
        Serial.print("\tfrequency Hz:");
        Serial.print("\tinductance uH:");

Sunday, 3 February 2013

SMD if there is a will there is a way

I couldn't wait for my breakout boards to arrive! I hope this encourages others to do some smd soldering... I used some rosin soldering flux from radio shack and a regular solder.

SMD breakout board

Wednesday, 16 January 2013

Virtual MSX disk drive

When I was a kid I had an MSX, a SVI-728 to be more precise, it's just a Z80 based computer with 64Kb of RAM. Mine used cassette tapes to load games and the loading times were eternal not to mentioned all the loading errors that required restarting the load from the beginning.

Other friends of mine had an MSX with a disk drive but I got still stuck with the tapes :-(

So... Revenge! I decided to build my own disk unit :-)

MSX's with a disk drive come with a disk BIOS that handles all the disk operations, from the lowest level (i.e.: read sector 23) to extending BASIC with new commands to list the available files in the disk, formating, deleting and creating files, and so on.

My first step was to get a disk BIOS from a MSX with a disk unit and patch the sector reading/writing routine so instead of talking to a disk unit, it would talk to another device, an Arduino.

Unfortunately I can't fit an 720Kb disk in an Arduino but since it has a USB connection it can ask my PC to get that sector form an certain disk image in my PC's hard's disk and send it thought the USB cable.

For that I need some gluing hardware between the MSX and the Arduino, here is the pic of the setup

Breadboard with arduino-msx gluing logic

And here are the schematics of the interface:


The trick of the trade

It all works thanks to the Z80's /WAIT pin, when an IN or an OUT instruction happens for an port below 31 the logic gates put this pin to a low sate making the Z80 wait, the Arduino notices that and can fetch the data from the computer and put it onto the 74245 buffer, then the Arduino will raise the /WAIT pin to make the Z80 resume the execution so the OUT instruction gets the data from the buffer.

The software bit on the MSX side...

My computer didn't have a disk BIOS so I had to get one, fortunately Arjen Zeilemaker had disassembled some and put the asm code in sourceforge. All I had to do was to write the DSKIO function to talk with my arduino, the code was so simple that I just used notepad and worked on the second run. I took a game cartridge and replaced the game's ROM with an 16Kb EEPROM I got from EBAY. As for writing the EEPROM I used a reader/writer I built once as a quick hack, I used for that a ATMEGA128 since it has enough pins to driver teh 28 pins you need to set in order to write or read an EEPROM.

Simple flash memory reader on the top, game cartridge on the bottom

The two white cables sticking out of the Atmega128 are the serial port, I wont tell what are the black and red ones :-)

..and on the PC side

I just used Python to read the commands coming from them MSX, the script will take the 512 bytes sector and will send it to the arduino and 1Mbit per second. The Arduino will send byte by byte to the Z80 at a similar speed.

Here is the video, sorry for the shaky hand :-) On the left you have the python script, on the right VLC media player.

Source code! :)

Ok here are the sources, sorry I didn't document the code so much, please let me know if you have any questions.