Showing posts with label uart. Show all posts
Showing posts with label uart. Show all posts

Sunday, August 2, 2015

Getting started with ESP8266, flashing the latest SDK

As promised, this is the ESP8266 post. So, if you have been reading about IOT projects, chances are you already heard or even used one of these. But in case you didn't, ESP8266 is a very cheap WiFi to serial converter .. or so they call it. It easily gives access to WiFi for any existing project with spare UART connection, and it can work both as an Access point(SoftAP mode) and a Station, and even do it simultaneously. Well enough of this, let's get to business..

Getting started

If you just type "esp 8266 getting started" in Google, the first link that comes is this pdf, and trust me, it has all the information that you need to get started. But just a quick analysis of what you will be doing.
You will need to communicate with the ESP8266 through UART, so you'll probably need a USB to serial converter, like one found on the Arduio, or any other FTDI usb-serial converters. You can even use your own if you have one. But before you start poking wires around - keep in mind, ESP8266 works at 3.3 volt, so don't hook it to your 5 volt Arduio. It's best to use a 3.3 volt usb-serial converter, but I didn't have one, what do we do ? Well, it's simple actually, we need few things. At first, a 3.3 volt regulator to power ESP8266. It should be capable to supply at least 200 mA. The more the better. And even if you can't find one, you probably can salvage it from an old motherboard or DVD drive. I got mine from salvaging.
Once you got that, one problem solved, one left - it's inputs are not 5 volt tolerant, so you'll need to logic level converter. May sound complicated, but there are a lot of simple schematics that will work for this case.

I used the zener diode version. It is even used in V-USB projects, but another post for that. The R1 value may need some tweaking, depending on the zener dide used. However, after you have both the voltage regulator and level shifter, we can start poking wires around.

Connections

Look at the pinout in the "getting started" guide, the connections are...
ESP8266 Serial converter
VCC 3.3V
CH_PD 3.3V
UTXD USB-Serial RX
USB-Serial TX 5VTX
URXD To 3.3VRX
GPIO0 To GND when flashing
GND GND
"What about USB-Serial TX?" you may ask. Well, it should consider 3.3 volts a logic one, so no problems there.
Once you got the connections ready, open the USB-Serial converter with a serial terminal program. In my case picocom worked well enough. Things to keep in mind with your serial terminal
  • use CR+LF for line endings
  • default baudrate should be 115200, although it may very
 With picocom it looks like this:
$ picocom -lb 115200 --omap crcrlf /dev/ttyUSB0
Where
  • -l says not to lock (locking needs root permisions)
  • -b sets the baudrate
  • --omap sets line ending to CRLF
Once it's open, the first test to do is writing AT, you should get an OK reply.
If you don't get any reply, or get some gibberish, check the baud rate, and lastly look at getting started guide for info.
Let's assume you did finally manage to get it. Now check the firmware version, type in
AT+GMR
 And you should get a response like the one I got
AT version:0.30.0.0(Jul  3 2015 19:35:49)
SDK version:1.2.0
compile time:Jul  3 2015 20:52:32
OK
The AT verions and SDK version may very. At time that this post was written, the latest version was esp_iot_sdk_v1.2.0_15_07_03, however, you may consider checking for the newest version.

Downloading latest SDK

After scrolling down on the link above, you'll see the attached zip file, download it and extract it somewhere. It contains the latest firmware binaries, that we will flash in next step. Except for the SDK we also will need to tool to flash the ESP8266. One awesome solution for this is the esptool. It's for linux users, but pretty sure you can run it on windows as well, if you try hard enough. Clone the repository where you saved the sdk..
$ git clone https://github.com/themadinventor/esptool.git

Why do this ?

Well few reasons, mine didn't work properly because of some bug in old version. If you find that your's is already the latest version, skip this step.

Flashing the binaries

Note: don't forget to power down, connect GPIO0 to GND, then power up ESP to put it in flash mode.
 esptool is pretty self explanatory. Go to the the extracted sdk folder and find bin folder. In it, at folder contains a readme. It will tell the proper files with proper flash addresses. Mine said:
boot_v1.2+.bin          0x00000
user1.1024.new.2.bin      0x01000
blank.bin               0x7e000 & 0xfe000
 So copy the files listed into the esptool folder, open a terminal there and start writing:
$ python2 esptool.py --port /dev/ttyUSB0 --baud 115200 write_flash 0x00000 boot_v1.2.bin 0x01000 user1.1024.new.2.bin 0x7e000 blank.bin 0xfe000 blank.bin
Where
  • --port tells the serial converter location (e.g. COM2 for windows)
  • --baud tells the baud rate
  • write_flash - well, tells to write to flash
  • then address, file pairs come in, the ones you found in the readme file
Note: for esptool to work you need python2-pyserial installed.
If everything goes planned, you will successfully write the latest firmware.
Connecting...
Erasing flash...
Writing at 0x00000400... (100 %)
Erasing flash...
Writing at 0x00040c00... (100 %)
Erasing flash...
Writing at 0x0007ec00... (100 %)
Erasing flash...
Writing at 0x000fec00... (100 %)

Leaving...

Aftermath

If everything went correct, you got a working ESP8266 with the latest SDK, congratulations. You can check  the version with AT+GMR command. 
You can find AT command list here and here. And a wiki page.
The getting started guide has examples of making TCP/UDP connections and etc. But I suppose, I'll talk about it in the next posts. Bye.

Friday, May 22, 2015

1 wire CRC checking

Well well, pretty long time since the last post, well what can I say, I'm still busy with school. However, recently (like a long time ago), when I was browsing avr-libc package's libraries, I stumbled upon a library, called util/crc16.h, which you may guessed, gives CRC checking utilities.
Now, in 1 wire exploration post, there was a CRC byte, when reading the scratchpad of DS18B20 temperature sensor. If you'd watch the datasheet, you would see that the equivalent polynomial function of the CRC was
CRC = X8 + X5 + X4 + 1
I'm not really sure what that means, but while browsing the library, I noticed a function named _crc_ibutton_update, which seemed to have the same CRC polynomial and was called iButton 8 bit CRC.
There was even an example code, but even without it, the function seems pretty convenient. Meaning that if we would take the code before, and make some changes, it would be:
    one_wire_receive (scratchpad, 9);

    uint8_t CRC = 0;
    for (i=0; i<8; ++i) {
      CRC = _crc_ibutton_update (CRC, scratchpad[i]);
    }

    if (CRC == scratchpad[8]) {
      debug_out ("CRC match!");
    }
    else {
      debug_out ("CRC mismatch :(");
    }

The new code can be found in the source code repository of the blog, under 1_wire_0/1_wire2_CRC.c. That's all for today!

Friday, February 6, 2015

Messing around an Electret microphone

Hello there .. again. It has been a while, so today we will be messing around an electret microphone. The mission for now is : Make a simple voice recorder. Of course we won't be getting studio quality (obviously), and that is .. for several reasons..
  1. ADC on Atmega16(the one that I got around) gives tops 15 kilosamples per second, and it's just 10 bits. While just CD quality requires 16 bit, 44100 kilosamples.
  2. Except for getting ADC values, we also need to send it somehow to the computer
  3. ... well you got the idea, whatever, moving on
BUT, we can still mess around, see the best we can do with minimal effort possible.

The action plan ..

So, the name electret comes from two words - electrostatic and magnet (wiki). It basically has two conducting plates, one of which is serving as a membrane, and when mechanical waves (i.e. sound) hits the membrane plate, it causes change of capacity, which will cause a change in voltage. Mostly all this type of microphones have a FET inside for gain, so all you would need to do is bias it with a resistor. For my case I used a 1k resistor.

So, we biased it, then what ? Then will just hook it onto one of Atmega16's differential input pins (Port A 3 - in my case) through a capacitor (~50 nF), and the negative pin of the differential input will be connected to the ground. Also, we could really use some gain.
Well, 10x sounds tempting, let's see. Ok, we have the idea of inputs, now sampling rate and resolution.. AVR's ADC offers us up to 10 bit resolution. Sending 10 bits to the computer .. what a drag.. if it would have been 8 bits, we could send it over to the computer using UART, seems like the most effortless way. Sure, we will loose those two bits .. but whatever, too much effort, not worth it. As for sampling rate, the important information when speaking is contained around 1-4 khz, so I'd guess 10,000 samples per second sounds pretty good. Assemble the schematic on your breadboard, and lets move on to the code.

Code

Once again, what we decided:
  • 10 kilosmaples per second
  • 8 bit resolution (ADLAR :)
  • UART feedback to the computer
  • Differential input channels
I guess the Free running mode for ADC was made just for this purposes. The clock for my MCU is 16 mhz. Divide it on 10,000, you'll get 1600. So if we divide our clock (clock_io) on that magical number - 1600, we'll get our sampling clock. 1600 = 8 * 200. Thus, if we choose the clock divider to be 1 : 8, we can fit in the 8 bit timer counter 0. Configure it on CTC mode to count from 0 to 199 (200 ticks), on 16 mhz / 8 frequency, the sampling clock is done. Now how to trigger the ADC on this event ? Well, several ways for this. The one that comes to mind - just make it start the conversion from the interrupt of Timer 0 Compare match - but that's a bad idea, we have free running mode made for this. So by configuring the ADC, we'll just say it to look up for Timer0 compare match flag, and when it gets set, start converting. When done, it'll call the interrupt handler for ADC finished, and we'll just send the byte of information out from the interrupt. CRITICAL: in order for ADC to start conversion, the selected interrupt flag should go from 0 to 1. So if you don't clear it, it will get stuck. If you enable hardware interrupt for current interrupt flag, it will clear the flag itself, but however, if you don't, just write logical one to the bit spot of that interrupt flag.
So, the function to start the Timer counter 0, pretty simple actually.
void init_timer0 (void) {
  /* 
   * 8 bit timer counter 0
   * Mode of operation: CTC
   * Divider: 8 / OCR - 199 (200 divider)
   * Interrupt frequency: 10000 hertz
   */
  TCCR0 = _BV(WGM01) | _BV(CS01);
  // TIMSK |= _BV(OCIE0);
  OCR0 = 199;
}
As for ADC initialization code, we set ADLAR (left adjust, for 8 bit resolution), highest possible clock speed, ADATE (automatic update trigger .. or whatever it was), and MUXes, for selected pins, at selected 10x gain. Also in SFIOR, we select the trigger for ADC to be Timer0 compare match.
void adc_init (uint8_t muxx) {
  SFIOR |= _BV(ADTS1) | _BV(ADTS0); // TIMER0 compare match
  ADMUX =  _BV(REFS0) | _BV(ADLAR)| muxx;
  ADCSRA = _BV(ADEN) | _BV(ADPS2) | _BV(ADIE) | _BV(ADATE)
    /* | _BV(ADPS1) */;
}
The interrupt handler in our design had two jobs - send data over UART, and clear the Timer0 compare match flag.
ISR (ADC_vect) {
  // send converted ADC data over uart
  UDR = ADCH;
  // clear TIMER0 compare match flag
  TIFR |= _BV(OCF0);
}
And the main routine - just call all the init functions, and sit back, and relax.

Processing the audio

Well, good, we opened the serial terminal with logging, and got bunch of crap that seems to be changing when we talk. What next ? What we get is not just useless code, we get code, representing our analog signal, or otherwise called raw data. I found that Audacity has a feature of importing raw data.

The resulting wave looked like this.
In case of any questions, comments are welcome. And all the code can be found here. Goodbye!