How to Make (Almost) Anything

Morgan Blevins

Week 7: Embedded Programming

The assignment this week is to program my board from week 5 to do something with as many different programming languages and environments as possible.

1. Programming Board

Blinking Code using Arduino environment CODE: I started with code code from Jaclyn Berry's page : const int buttonPin = 7; const int ledPin = 2; int buttonState = 0; void setup() { pinMode(ledPin, OUTPUT); pinMode(buttonPin, INPUT); } void loop() { buttonState = digitalRead(buttonPin); if (buttonState == HIGH){ digitalWrite(ledPin,HIGH); } else{ digitalWrite(ledPin,LOW); } } The key steps to adapting this to my board are pretty simple. All I have to do is change the pins to work with my board and to adjust certain board/programmer settings in the arduino environment. This diagram shows what the pins are named in the eyes of Arduino vs. what you see on the schematic. My LED pin is A7 and my switch pin is A2. I changed the code to toggle between blinking or being a solid light based on the button press. My final code was this (.ino file linked here): const int buttonPin = A2; //define button locations const int ledPin = A7; //define LED location int buttonState = 0; //button state defined as low to start int count = 0; //set up a counter to change the LED state void setup() { pinMode(ledPin, OUTPUT); //set LED as output pinMode(buttonPin, INPUT); //set button as an input } void loop() { buttonState = digitalRead(buttonPin); //read state of button //Blink option: if (buttonState == HIGH && count ==0){ //if button is off and you're on state1 digitalWrite(ledPin,LOW); delay(100); digitalWrite(ledPin,HIGH); delay(100); } //Solid option: else if (buttonState == HIGH && count ==1){ digitalWrite(ledPin,HIGH); } //When button is pressed: else{ digitalWrite(ledPin,LOW); count = count +1; if (count >1){ count=0; } else{ } } } CONNECTING BOARD & PROGRAMMER: For this set up my settings under the Arduino tool menu were: Board: "ATtiny 24/44/84" Processor: "ATtiny44" Programmer: "USBTinyISP" (1) Arduino was not identifying my USBtiny & my programmer didn't seem to be getting powered properly. After trouble shooting for a while I realized one issue was that the connecting cable I made for my board and programmer wasn't working properly. When I got new wires and connected the two boards Arudino was able to find my board! The no longer working cable :'( : (2) Another key issue was that I did not have the driver downloaded for the USBtiny. When I went to computer connected devices I saw that it said that the driver was "unavailable", so I had to go online and download a driver- then it worked! love it. Here is what it showed in my "other devices" once I had the driver: It successfully uploaded and the button could toggle between blinking the light or keeping it static! (2) Blinking Program using C-program & Makefile I started with Rob Hart's code . This comes with both a C file and a make file. His code turns on an LED in response to a button press To adapt it I did the following: (1) Toggle between a blinking state and a solid state (2) Changed the pin assignments Here is the code I wrote: #include #define bit_get(p,m) ((p) & (m)) #define bit_set(p,m) ((p) |= (m)) #define bit_clear(p,m) ((p) &= ~(m)) #define BIT(x) (0x01 << (x)) // Button PA5 (pin 8). // LED PB2 (pin 5). int main() { bit_set(PORTA,BIT(5)); // Turn button pull up resistor on by setting PA5(input) high bit_set(DDRB,BIT(2)); // Enable output on the LED pin (PB2) while (1) { if(bit_get(PINA,BIT(5))) // Button is up, turn off bit_clear(PORTB,BIT(2)); else // Button is down, turn on bit_set(PORTB,BIT(2)); } } Getting the c-stuff to work on my computer: I followed Julia Ebert's process for uploading C-programs to an Attiny44. ISSUES: (1) At first "make" didn't work. I had to follow the process here (written by Brian) that took me through installing the Atmel GNU Toolchain, installing GNU Make, installing avrdude, and updating my PATH. NOTE ON PATH: I was having issues with my PATHs even after exactly following this process above. When I tested "avr-gcc --version" in my terminal is said command not found. I found this resource that showed me that you sometimes have to write the "Program Files" portion of the path as "PROGRA~1" to fix issues involving the space in the name. It worked! Happy PATHs: (2) Now make was working and my paths were correct but I kept getting this error. After a lot of trouble shooting I realized that when I was downloading the echo files Windows was adding a .txt to the end of both files. In Atom I renamed the files and finally the make function worked, I got my hex file!: So to review, the process is as follows: (1) Open terminal in directory w/ the C and make file (2) Comile & make hex file make -f hello.ftdi.44.echo.c.make Now all I have to do is (3) Send the file to the board: make -f hello.ftdi.44.echo.c.make program-usbtiny (4) Set the clock on the board: make -f hello.ftdi.44.echo.c.make program-usbtiny-fuses ~~~~~~change the c and make file names to match the project you care about~~~~~~~~~ Embedded Programming I started to do for my final: I started with Neil's blinking program (written in C). In this program an LED turns on in response to a button being pressed. I want to change it so that a button press makes a string of lights toggle between different color patterns. This will be integrated into my final project in the housing of the UFO buoy. I reconfigured my board to use this tri-colored LED Here is the C-Code I wrote to toggle the color changing LED: // Copied from Rab Hart's code that was... //Shamelessly copied and mofied from Neil Gershenfeld's for purposes of instruction. //This cycles the color pattern of LEDs in response to button press //For the ATTINY44 // Button PA2 (pin 8). // RED PA7 (pin 5). // GREEN PA6 // BLUE PA5 #include < avr/io.h> // this includes all definitions of registers and bits of registers, including pins and port names. #define output(directions,pin) (directions |= pin) // set port direction for output #define input(directions,pin) (directions &= (~pin)) // set port direction for input #define set(port,pin) (port |= pin) // set port pin #define clear(port,pin) (port &= (~pin)) // clear port pin #define pin_test(pins,pin) (pins & pin) // test for port pin #define bit_test(byte,bit) (byte & (1 << bit)) // test for bit set #define input_port PORTA // The button is on port A #define input_direction DDRA // DDRA defines input/output for port A #define input_pin (1 << PA2) // The button is on pin 5 of port A (1<< PA5) = (1<< 5) = 0b00100000 #define input_pins PINA // PINA is the register that is read to detect input high or low. #define output_port PORTA // port B will be used for the LED #define output_direction DDRA // DDRB defines input/output for port B #define output_red (1 << PA7) // #define output_grn (1 << PA6) #define output_blu (1 << PA5) const int i = 0; int main(void) { // // main function. // // initialize pins output(output_direction, output_pin); // set output for LED pin. set(input_port, input_pin); // turn on internal pull-up input(input_direction, input_pin); // set button pin for input. // main loop while (1) { if (pin_test(input_pins,input_pin)) //test button pin. if(i==0){ set(output_port,output_red); i++; } if(i==1){ set(output_port,output_grn); clear(output_port,output_red); i++; } if(i==2){ set(output_port,output_blu); clear(output_port,output_grn); i++; } if(i==3){ set(output_port,output_red); i++; } if(i==4){ set(output_port,output_grn); i++; } if(i==5){ clear(output_port,output_blu); i++; } if(i==6){ clear(output_port,output_red); i++; } if(i==7){ clear(output_port,output_grn); i=0; } else // if button isn't pushed, stay how you are! } } I then did the same program in Arduino: The code I wrote in week 5 (onthe left) and the code I made for this type of blinking. I haven't uploaded these yet before I don't have the board built yet! But it as good practice in embedded progamming and hopefuly I won't have to change these too much when I have the board built for them to work.

2. Reading Datasheet & prepping final project board

For the programmer this week I used the board I made in week 5, but in my final project I will be changing my board a lot and switching to the ATMEGA16U microcontroller. This week I read the datasheet for the ATMEGA16U2-AU. These cost about $2 when you buy in bulk. Here is the datasheet for the ATMEGA16U. This is 300+ pages so I've highlighted the key information here:
The ATMEGA16U This is an 8-bit AVR microcontroller. This means that all the messages it reads or writes are 8-bits long. AVR is the specific family of microcrollers that this one belongs to. AVR microcontrollers run on the Harvard architecture system, where separate memory systems are used to store instructions and data (Wikipedia page for Harvard Arch). This is the 16K Byte version, so there are 16K Bytes of In-System Self-Programmable Flash (ISP Flash). Here is the block diagram of the microcontroller: The listed features are: 8K/16K/32K Bytes of In-System Programmable Flash with Read-While-Write capabilities allows the program memory to be reprogrammed in-system through an SPI serial interface, by a conventional nonvolatile memory programmer, or by an on-chip Boot program running on the AVR core 512/512/1024 Bytes EEPROM, 512/512/1024 SRAM, 22 general purpose I/O lines 32 general purpose working registers two flexible Timer/Counters with compare modes and PWM one USART a programmable Watchdog Timer with Internal Oscillator an SPI serial port debugWIRE interface (also used for accessing the On-chip Debug system and programming and five software selectable power saving modes) Here is the pinout of the microcontroller: Let's talk about this pin out shall we!! GND and V_CC (pins 3 and 4, switched between the two different configs) are the ground and power of the microcontroller. I added an LED to indicate when the chip is being powered and a bypass cap to gnd. AVCC (pin 32) is the power source to the analog pins. I think of this like Analog + VCC. Port B pins (pins PB7-PB0, pins 14-21 for both pinout configs) "Port B is an 8-bit bi-directional I/O port with internal pull-up resistors (selected for each bit). The Port B output buffers have symmetrical drive characteristics with both high sink and source capability. As inputs, Port B pins that are externally pulled low will source current if the pull-up resistors are activated. The Port B pins are tri-stated when a reset condition becomes active, even if the clock is not running" So these pins can act as input or output ports, as defined by the used in embedded programming. Pins 17, 16, and 15 are the MISO, MOSI, and SCLK pins for communicating with the programmer. Here is connect them to a 6-pin header for interfacing to the programmer (either the one from week 5 or the Atmel-ICE (AVR) in the lab). Ideally I'd like to program my board on my own some day, so being able to program w/ an arduino would be really nice. There are a ton of articles online on how exactly to do this. You can also program this chip via USB port because it comes with DFU (device fireware updater) bootloader. I'm not sure what approach will be beter for me. I'm still inteimiadated by setting fuses, make files, etc. The arduino route is certainly less involved/intimidating. Port C pins (pins PC7-PC0, pin locations a little spreadout for both pinout configs) These pins act just like port B pins. Recall pins can have alternate functions! PC0 is the XTAL2 pin, PC1 is reset. big questions... where is PC3??? Port D pins (pins PD7-PD0, pins 6-13 for both configs) This port serves as the analog inputs to the analog comparator. What's an analog comparator? It's this (and we can see it on the left side of the block diagram): "An analog comparator can be used to compare two voltage levels and based on that it can be used to generate a logic output (0 or 1) to indicate which of the two levels is higher or lower than the other." Source The Analog Comparator compares the input values on the positive pin AIN0(PD0) and negative pin AIN1 (PD1). When the voltage on the positive pin AIN0 is higher than the voltage on the negative pin AIN1, the Analog Comparator output, ACO, is set (bit 5 of the Analog Comparator Control and Status Register). If the analog comparator is not used (PD2/PD1 pins) Port D acts just like port B or C. I'm not using the analog comparator! There are 22 programmable Input/Output (aka I/O) pins. The 22-programmable pins are coming out of the PORTD, PORTC, and PORTB drivers. D+ and D- pins (pins 29 and 30) These are the USB Full Speed Negative Data Upstream Port and Positive Data Upstream Ports, respectively. These pins are how I am going to connect my computer to my board- via a microusb! I learned about this through Andrew Mao's page , and he used this Arduino Uno schematic to make his: UGND This is the ground for the USB ports UVCC This is the input supply voltage for the USB internal regulator UCAP This is the output supply voltage for the USB internal regulator. This should be connect to a capacitor. RESET/PC1/dW This is the reset input. Setting this pin low for longer than the minimum pulse length with generate a reset! We used his pin with you attiny in week 5, connecting it to VCC via a resistor. This connects to the programmer. XTAL1 This is the input to the inverting oscillator amplifier (and also input to the internal clock) XTAL2/PC0 This is the output from the inverting oscillator amplifier (also can be a generic I/O.) "Pins XTAL1 and XTAL2 are input and output, respectively, of an inverting amplifier which can be configured for use as an On-chip Oscillator, as shown in Figure 8-4. Either a quartz crystal or a ceramic resonator may be used. This Crystal Oscillator is a low power oscillator, with reduced voltage swing on the XTAL2 output. It gives the lowest power consumption, but is not capable of driving other clock inputs, and may be more susceptible to noise in noisy environments." p. 30 So this is where we can hook up a quartz crystal or a ceramic resonator to create a faster clock. --- notes on his page that a fast quartz clock is needed to support full speed USB communication. The Arduino Uno uses a 16Hz crystal and that's what -- used too. Clock: The device is shipped with internal RC oscillator at 8.0 MHz and with the fuse CKDIV8 programmed, resulting in 1.0 MHz system clock. Sensors BMP280: The ATMEGA16U uses SPI via the MOSI/MISO pins and that is how we will communicate with this sensor.