Showing posts with label micro controllers. Show all posts
Showing posts with label micro controllers. Show all posts

Wednesday, 1 July 2015

Atmel Studio 6.2 and atmega328p Serial Comms

As part of my ongoing Lab Power Supply project I thought that it was time I learned to use Atmel Studio. While Arduino is pretty quick to get things going I really started to hit its limits in the dummy load project. Just managing lots of Windows gets hard and I ran into problems when I tried using microprocessors not supported by the IDE.

I also want to experiment with JTAG ICE debugging and I think Atmel Studio will make this much easier than other approaches (such as using WinAVR and the GDB command line).

My plan was to experiment with using a USB to UART chip in conjunction with an isolator chip to create a galvanically isolated USB port for the power supply.

Atmel Studio 6.2

I downloaded the code from the Atmel web site. It is a huge download at just over 500MB. Then when it downloaded it needed to download and install the Visual Studio IDE. Finally the thing installs and the first thing it does is pops up and tells me there is an update the the ASF (Atmel Software Framework) which then downloads another 140MB or so.

I'm quite familiar with Visual Studio as I use it for C++ development during my day job. Atmel Studio felt pretty similar. I was able to quickly create a C++ project for an ATMEGA328P. Weirdly it pretty much immediately warned me that some of the ASF won't work in a C++ project and I should use C. Undeterred I pushed on. 

I tried the ASF thing but found it pretty confusing. Before you can begin you have to choose a board. I am basically using the micro in a breadboard so I wasn't sure what to choose. There was a 'generic' "user board template megaAVR' board option so I went with that. The list of libraries in the ASF wizard is pretty confusing too - things that would have been there out of the box in Arduino appear to be libraries. For example there is a ADC driver, a Delay routines service a GPIO and an IOPORT service (no I don't know what the difference is either). Each of these opens a little folder and has a link to documentation and shows you the headers for that option. 

Amusingly there is a unit test framwork which appears to be C unit. I later found you have to use this in a separate project from your target project. Unit testing would be very nice.

A nice way of describing the user documentation is sparse. I haven't yet discovered the sample code (if there is any). Basic tasks often require direct access to registers etc.

When I have gone looking I found that things which are basic in Arduino aren't so basic in Atmel Studio. Also you lack lots of library support for things and people tend to code their own. It will be much more work using this but I am hoping it is worth it. Also there is an option to use the Arduino libraries from within Atmel Studio but I haven't explored this yet.

I compiled the empty project, set a breakpoint and hit F5. It popped up a dialog asking me to choose the target but the only option was a simulator. Running in a simulator is nice for unit-testing I suppose. This seemed to work as expected and the debugger seemed like it would be useful if the project actually did something.

Programming the Chip

Unfortunately Atmel Studio only comes as a Windows tool so I am running it on a Windows 7 VM under parallels on my Mac. Initially I plan to use an AVRasp programmer but later will try out a JTAG programmer.

Annoyingly Atmel Studio doesn't support this programmer directly so you have to configure avrdude as an external tool and use that to program the chip. I installed WinAVR which adds avrdude to the path. The command line options are described quite well here

I found this would not detect my usbasp device. I had to go to this site , download the drivers and then right-click the device in Device Manager and update the drivers from the downloaded ones.

To add avrdude to the Atmel Studio project you go to tools -> external tools and add something like this (see image). First browse to the avrdude exe, then for the parameters add:

 -c usbtiny -p atmega328p -F -U flash:w:"$(ProjectDir)Debug\$(ItemFileName).hex":i

De-select the 'close on exit' check box as otherwise if something goes wrong you won't see the error. Here is what it looks like:


Serial

My plan is to eventually control each Lab PSU channel using text commands sent over a USB->UART bridge. For now I just want to be able to print something. On the Arduino this is easy but pretty basic.

I tried searching the documentation and while there were links to USART stuff it all seemed to be related to specific board configurations I wasn't running. Apparently there is a ReMORSE example app somewhere for the ATMEGA328P but I am buggered if I can find it.

I Googled for examples and found that to make serial work you essentially have to provide functions for getting or putting a single character to the serial interface and then wire these into a FILE structure. From there you can replace the stdin or stdout globals with your own so when you call printf() or scanf() etc it uses the serial port.

The example code I found would basically do this:

FILE uart_io = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);

This uses a macro to set the fields of the FILE structure during initialization. When I did this I got this error:

C:\Users\fred\Documents\Atmel Studio\6.2\LabPSU\LabPSU\LabPSU.cpp(33,18): error: sorry, unimplemented: non-trivial designated initializers not supported

It turns out that this macro uses a language feature that never made it into the C++ spec and hence you get this error. I found there was a function that did something similar however so I could do this instead:

    FILE uart_io;
    memset(&uart_io,sizeof(uart_io),0);
    fdev_setup_stream(&uart_io,serialWrite,serialRead,_FDEV_SETUP_RW);


Now I needed functions to emit or consumer characters from the serial interface. Most of the code I found on the net did this with busy wait loops which seemed positively medieval. I found a library by Peter Fleury that implemented putting/getting characters from the serial interface using interrupts and a ring buffer here. This seemed much better!

I had to create bindings to allow this to interface with the functions expected by the FILE structure so I created a pair of functions like this, I'm not worrying about errors as I don't think there is anything that can be done anyway,

int serialWrite(char c, FILE *fp)
{
    uart_putc(c);
    return 1;
}

int serialRead(FILE *fp)
{
    return uart_getc();
}



Then I registered these using the snippet above. Once that is done I can do things like this and the output should turn up on the serial port.


    int i=0;
    
    while(1)
    {
        printf("Testing... %d\r\n",i++);   
    }

When I first compiled this and programmed it onto the chip nothing happened. No output and no signs of life. I ended up creating a blinking LED program just to make sure I was programming the chip correctly and this worked.

Eventually I found another copy of this library but this copy included an example program. In that he included avr/interrupt.h and called the function sei() before using the UART functions. I added this code and it worked!

Note in the code example above I am printing \r\n as for whatever reason without this the output moves to the next line but doesn't return to the start of the line. Given the output is going to a Mac I would have thought just \n would be fine. Anyway no matter. This looks like a starting point.

Isolated Interface

The bit I didn't mention is my hardware setup. I plan to use an MCP2200 USB bridge chip from Microchip. I bought a breakout board for one of these from RS (for like $20! Cheap!). Initially I just connected it to a computer (my Mac) and typed characters at it while watching what happened on the RX port. My Mac already had a driver for it so I just plugged it in and used screen to connect to /dev/tty.usbmodem1411. That was pretty easy.

There is some software from Microchip for configuring the device but this is Windows only. I installed the drivers onto my Windows 7 VM and ran the tool. I configured some of the GPIOs to blink LEDs and this seemed to work. Overall this looked really good.

Next I connected my microcontroller to it and used the VDD and GND pins to power the micro controller. This worked and I could see the test serial output from the micro controller via the screen tool.

Now for this to work in m lab power supply it needs to be electrically isolated from the USB power. I bought one of the Analog devices ADuM1201 chips from RS. They are relatively cheap and very simple. You have two power and ground ports and you have an in and an out port on each side. The two sides are isolated from each other but the data signal goes through.

I powered one side of the chip from the MCP2200 breakout and the other side from a bench PSU (my Jaycar PSU configured for 5V). When I power up the bench PSU I can see the comms on the screen tool. If I put my scope on the pins I can see the traffic. Interestingly if I connect the ground to the opposite side from where I am connecting the signal the voltage floats around as you would expect.

This looks super easy and I think is the way to go.

Saturday, 6 April 2013

ATTiny85-10PU

Arduino Uno

Ages ago I bought an Arduino as I had a project in mind involving monitoring of a solar inverter at a site that is infrequently visited during winter.. The plan was to read the inverter status using MODBUS over RS485, log the time of day and voltage/readings into a file on an SD card.

I made some progress but then ran out of time/interest. I will probably go back to it. The hard part is the MODBUS interface as I have to take all my kit to where the inverter is to work on it.

Project

Anyway my son came to me with a project to construct a container that can protect a wine glass dropped from a 4 story building. His plan was to use an accelerometer to find out when the object is falling and then activate a servo that deploys a parachute.

We don't want to drop an Arduino off a building so the tool of choice was an ATTiny. The ATTiny 85s are super cute 8 legged chips that contain a complete microcontroller and need no external parts to run!

The first problem is that the standard servo library doesn't work on this uC as the built in timers are different. There is an alternative version available from here http://www.cunningturtle.com/attiny4585-servo-library/

First things first, my son ran some simple examples on the Arduino, made LEDs blink, made servos sweep etc. Easy.

Now the ATTiny came in the post so we wanted to program one of these.

Programming an ATTiny

To begin with I just wanted to see blink work on the ATTiny but this proved harder than it looks.

First to program the ATTiny you use the Arduino as an In System Programmer (ISP). There are instructions for doing this here http://hlt.media.mit.edu/?p=1695 that work for the 1.0.4 Arduino IDEm and the Arduino Uno (which we have). The important points are:


  1. Connect the ATTiny as follows: Pin 8 (of chip) to VCC, Pin 4 Gnd, Pin 7 (SCK) to Arduino Pin 13, Pin 6 (MISO) to Arduino Pin 12 and Pin 5 (MOSI) to Arduino Pin 11, Pin 1 (RESET) to Arduino pin 10
  2. DON'T put the capacitor between Gnd and Reset on the Arduino yet!
  3. In the Arduino IDE, with everything setup normally for programming the Arduino (i.e. board is Arduino UNO) load the example called ArduinoISP. Load this into the Arduino.
  4. Unplug, put a capacitor between GND and RESET. Note the stripe must go to GND if you are using an electolytic capacitor.
Now you have to make the Arduino IDE know about an ATTiny. Go here and download the zip https://github.com/damellis/attiny/archive/master.zip Open the zip and copy the attiny folfrt into your Arduino IDE folder under the hardware folder. Restart the Arduino IDE.

Now go to the Tools->Board menu and you should see a bunch of ATTiny options. There is no 10MHz option which confused me to begin with. Choose 8MHz ATTiny 85 (you want to use the 8MHz clock speed to make the 8Bit servo library work).

Now choose tools->burn bootloader. This will set the fuse bits to make the chip run at 8MHz as well as some other settings. You will get a warning like:

avrdude: please define PAGEL and BS2 signals in the configuration file for part ATtiny85

but you can ignore this.

Now load the blink example sketch, change the led pin to 0 instead of 13 and upload this. Again you get the PAGEL etc warning and it is done. Connect a 330Ohm resiste and LED to pin 5 of the chip and it should blink!

Stuff that went wrong

It took a *lot* of stuffing around to get to this point. It took a while to twig about running the Arduino ISP sketch and THEN uploading to the ATTiny. Ditto the reset pin capacitor.

I got an error along the lines of 

avrdude: Yikes! Invalid device signature
               Double check connectiona and try again, or use -F to override this check

The fact that my ATTiny is a 10MHz one and not an 8 meant I kept wondering if this was the cause of the problem. I though that I should be able to run it at 8 by setting the fuses but it refused to work.

The invalid device signature problem was caused by me confusing the drawing that shows how to wire up the ATTiny. The picture was rotated compared with our setup and I accidentally had SCK and MOSI the wrong way round.

After this I was able to burn the bootloader. Then I tried to burn the sketch but this failed with a verification failure:

avrdude: please define PAGEL and BS2 signals in the configuration file for part ATtiny85
avrdude: verification error, first mismatch at byte 0x000         
                        0x47 != 0x00
avrdude: verification error; content mismatch

This turned out to be to do with power. I read that noise can cause problems and that putting a cap across the supply lines can fix this but for me it didn't. The problem was that the power lines on the Arduino are in between the legs of the reset capacitor and we had it plugged into 3.3v instead of 5v. Once I corrected this the sketch burned Ok and I could run blink.