Arduino Esplora
ATMega32u4
ISP programming
Bootloader programming The bootloader is basically a.hex file that runs when you turn on the board. It is very similar to the BIOS that runs on your PC. It does two things. First, it looks around to see if the computer is trying to program it. If it is, it grabs the program from the computer and uploads it into the ICs memory (in a specific location so as not to overwrite the bootloader). That is why when you try to upload code, the Arduino IDE resets the chip. This basically turns the IC off and back on again so the bootloader can start running again. If the computer isn t trying to upload code, it tells the chip to run the code that s already stored in memory. Once it locates and runs your program, the Arduino continuously loops through the program and does so as long as the board has power.
Arduino Esplora board
Default Clock Source The device is shipped with internal RC oscillator at 8.0MHz and with the fuse CKDIV8 programmed, resulting in 1.0MHz system clock. The startup time is set to maximum and time-out period enabled. (CKSEL = "0010", SUT = "10", CKDIV8 = "0"). The default setting ensures that all users can make their desired clock source setting using any available programming interface. Other clock sources Low power crystal oscillator crystal External oscillator Low frequency crystal oscillator Used for real time clock
Clock systems
Digital devices Diodes External switch
Bitwise operators: & AND OR ~ NOT << SHIFT LEFT >> SHIFT RIGHT ^ EXCLUSIVE OR Example: Bitwise AND PORTD = 0b???????? Number= 0b11111011???????? unknown bits & 11111011 =?????0?? result: one bit cleared Example: Bitwise OR PORTD = 0b???????? Number= 0b00000100???????? unknown bits 00000100 =?????1?? result: one bit set
Bitwise operators: & AND OR ~ NOT << SHIFT LEFT >> SHIFT RIGHT ^ EXCLUSIVE OR Example: Bitwise NOT PORTD = 0b10101010 ~PORTD = 0b01010101 Example: Bitwise SHIFT PORTD = 0b10101010 PORTD<<1 = 0b01010100 Example: Exclusive OR PORTD = 0b10101010 Number = 0b110011 00 0b10101010 ^ 0b11001100 = 0b01100110
Hex numbers: 0b00000001 = 0x01 0b00000010 = 0x02 0b00000100 = 0x04 0b00001000 = 0x08 0b00001100 = 0x0C 0b11110001 = 0xF1 0b10001000 = 0x88 ~0x01 = 0xfe ~0x02 = 0xfd ~0x04 = 0xfb Makro _BV(x): _BV(0) = 0b00000001 _BV(1) = 0b00000010 _BV(2) = 0b00000100 _BV(3) = 0b00001000 _BV(4) = 0b00010000 _BV(5) = 0b00100000 _BV(6) = 0b01000000 _BV(7) = 0b10000000 ~_BV(0) = 0b11111110 ~_BV(0) = 0b11111101 ~_BV(0) = 0b11111011 ~_BV(0) = 0b11110111 ~_BV(0) = 0b11101111 ~_BV(0) = 0b11011111 ~_BV(0) = 0b10111111 ~_BV(0) = 0b01111111
Shifted numbers _BV(0) = 0b00000001 = (1<<0) _BV(1) = 0b00000010 = (1<<1) _BV(2) = 0b00000100 = (1<<2) _BV(3) = 0b00001000 = (1<<3) _BV(4) = 0b00010000 = (1<<4) _BV(5) = 0b00100000 = (1<<5) _BV(6) = 0b01000000 = (1<<6) _BV(7) = 0b10000000 = (1<<7) ~ (1<<0) = 0b11111110 ~ (1<<1) = 0b11111101 ~ (1<<2) = 0b11111011 ~ (1<<3) = 0b11110111 ~ (1<<4) = 0b11101111 ~ (1<<5) = 0b11011111 ~ (1<<6) = 0b10111111 ~ (1<<7) = 0b01111111 (1<<0) = (1<<PORTD0) (1<<1) = (1<<PORTD1) (1<<2) = (1<<PORTD2) (1<<3) = (1<<PORTD3) (1<<4) = (1<<PORTD4) (1<<5) = (1<<PORTD5) (1<<6) = (1<<PORTD6) (1<<7) = (1<<PORTD7)
General purpose input/output schematic Pullup transistor Output to pin Input from pin
Port D registers
Using PORT names Using Arduino library Pin 2 as input internally pulled up pin 2 = PORTD, 2 (Uno) DDRD = DDRD & 0xFB; (input) pinmode(2, INPUT_PULLUP); PORTD = PORTD 0x04; (pullup) Pin 2 as input floating (high Z) pin 2 = PORTD, 2 (Uno) DDRD = DDRD & 0xFB; (input) pinmode(2, INPUT); PORTD = PORTD & 0xFB; (floating) Pin 13 as output pin 13 = PORTB, 5 (Uno) DDRB = DDRB 0x20; PORTB = PORTB 0x20; PORTB = PORTB & 0xDF; pinmode(13, OUTPUT); digitalwrite(13, HIGH); digitalwrite(13, LOW);
Using PORT names Using Arduino library Pin 2 as input internally pulled up pin 2 = PORTD, 2 (Uno) DDRD = DDRD & ~ _BV(2); (input) PORTD = PORTD _BV(2) ; (pullup) pinmode(2, INPUT_PULLUP); Pin 2 as input floating (high Z) pin 2 = PORTD, 2 (Uno) DDRD = DDRD & ~ _BV(2); (input) PORTD = PORTD & ~ _BV(2); (floating) pinmode(2, INPUT); Pin 13 as output pin 13 = PORTB, 5 (Uno) DDRB = DDRB _BV(5); PORTB = PORTB _BV(5); PORTB = PORTB & ~ _BV(5); pinmode(13, OUTPUT); digitalwrite(13, HIGH); digitalwrite(13, LOW);
Using PORT names Using Arduino library Pin 2 as input internally pulled up pin 2 = PORTD, 2 (Uno) DDRD = DDRD & ~ (1<<DDD2); (input) PORTD = PORTD (1<<PORTD2); (pullup) pinmode(2, INPUT_PULLUP); Pin 2 as input floating (high Z) pin 2 = PORTD, 2 (Uno) DDRD = DDRD & ~ (1<<DDD2); (input) PORTD = PORTD & ~ (1<<PORTD2); (floating) pinmode(2, INPUT); Pin 13 as output pin 13 = PORTB, 5 (Uno) DDRB = DDRB (1<<DDD5); PORTB = PORTB (1<<PORTD5); PORTB = PORTB & ~ (1<<PORTD5)); pinmode(13, OUTPUT); digitalwrite(13, HIGH); digitalwrite(13, LOW);
Cod in AtmelStudio: int main(void) { setup(); while (1) loop(); return 0; Cod in Arduino setup(); loop(); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// void setup (void) { // the setup function runs once when you press reset or power the board //funkcja setup jest wykonywana 1x po resecie lub podaniu zasilania void loop(void) { // the loop function runs over and over again forever //funkcja loop() jest wykonywana w kółko w nieskończonej pętli
Example: blinking LED Using Arduino library void setup() { pinmode(13, OUTPUT); void loop() { digitalwrite(13, HIGH); delay(1000); // wait for a second digitalwrite(13, LOW); delay(1000); Using PORT names (Uno) void setup() { DDRB = DDRB 0x20; void loop() { PORTB = PORTB 0x20; delay(1000); // wait for a second PORTB = PORTB & 0xDF; delay(1000);
Example: serial monitor Serial monitor is an application on PC connected to USART via USB int incomingbyte = 0; // for incoming serial data void setup() { Serial.begin(9600); // opens serial port, sets data rate to 9600 bps void loop() { // send data only when you receive data: if (Serial.available() > 0) { // read the incoming byte: incomingbyte = Serial.read(); // say what you got: Serial.print("I received: "); Serial.println(incomingByte, DEC);
Serial.write(33); Serial.write(33) gives!" Serial.print(33); Serial.print(33) gives 33" Serial.print(1.23456) gives "1.23" Serial.print('N') gives "N" Serial.print("Hello world.") gives "Hello world." Serial.print(78, BIN) gives "1001110" Serial.print(78, OCT) gives "116" Serial.print(78, DEC) gives "78" Serial.print(78, HEX) gives "4E" Serial.println(1.23456, 0) gives "1" Serial.println(1.23456, 2) gives "1.23" Serial.println(1.23456, 4) gives "1.2346"
void setup() { Serial.begin(9600); int thisbyte = 33; void loop() { Serial.write(thisByte); Serial.print(", dec: "); Serial.print(thisByte); Serial.print(", hex: "); Serial.print(thisByte, HEX); Serial.print(", oct: "); Serial.print(thisByte, OCT); Serial.print(", bin: "); Serial.println(thisByte, BIN); if (thisbyte == 126) { thisbyte = 33; // go on to the next character thisbyte++;
Example: button (Esplora) const int buttonpin = 3; const int ledpin = 13; int buttonstate = 0; // PORTD0 // PORTC7 // variable void setup() { pinmode(ledpin, OUTPUT); // initialize the LED pin as an output: pinmode(buttonpin, INPUT_PULLUP); // initialize the pushbutton pin as an input: void loop() { buttonstate = digitalread(buttonpin); // read the state of the pushbutton value: if (buttonstate == HIGH) { // turn LED on: digitalwrite(ledpin, HIGH); else { // turn LED off: digitalwrite(ledpin, LOW); // check if the pushbutton is pressed.
Example: button (Esplora) const int ledpin = 13; int buttonstate = 0; // PORTC7 // variable void setup() { DDRC // initialize the LED pin as an output: DDRD // initialize the pushbutton pin as an input: PORTD //input pullup void loop() { buttonstate = PIND & (1<< PINDx); // read the state of the pushbutton value: // buttonstate = PIND & _BV(PINDx); if (buttonstate == 0) { // turn LED on: PORTC else { // turn LED off: PORTC
Analog devices - switches and multiplexer
Stałe z biblioteki Esplora const byte JOYSTICK_BASE = 16; const byte MAX_CHANNELS = 13; const byte CH_SWITCH_1 = 0; const byte CH_SWITCH_2 = 1; const byte CH_SWITCH_3 = 2; const byte CH_SWITCH_4 = 3; const byte CH_SLIDER = 4; const byte CH_LIGHT = 5; const byte CH_TEMPERATURE = 6; const byte CH_MIC = 7; const byte CH_TINKERKIT_A = 8; const byte CH_TINKERKIT_B = 9; const byte CH_JOYSTICK_SW = 10; const byte CH_JOYSTICK_X = 11; const byte CH_JOYSTICK_Y = 12; const byte SWITCH_1 = 1; const byte SWITCH_2 = 2; const byte SWITCH_3 = 3; const byte SWITCH_4 = 4; const byte SWITCH_DOWN = SWITCH_1; const byte SWITCH_LEFT = SWITCH_2; const byte SWITCH_UP = SWITCH_3; const byte SWITCH_RIGHT = SWITCH_4; const byte JOYSTICK_DOWN = JOYSTICK_BASE; const byte JOYSTICK_LEFT = JOYSTICK_BASE+1; const byte JOYSTICK_UP = JOYSTICK_BASE+2; const byte JOYSTICK_RIGHT = JOYSTICK_BASE+3; const int ACCEL_ZERO_X = 320; const int ACCEL_ZERO_Y = 330; const int ACCEL_ZERO_Z = 310; const byte MUX_ADDR_PINS[] = { A0, A1, A2, A3 ; const byte MUX_COM_PIN = A4; const int JOYSTICK_DEAD_ZONE = 100; const byte RED_PIN = 5; const byte BLUE_PIN = 9; const byte GREEN_PIN = 10; const byte BUZZER_PIN = 6; const byte ACCEL_X_PIN = A5; const byte ACCEL_Y_PIN = A11; const byte ACCEL_Z_PIN = A6; const byte LED_PIN = 13;
Multiplekser 74HC4067 Funkcja biblioteczna unsigned int _Esplora::readChannel(byte channel) Uproszczona: unsigned int readchannel_simple(byte channel) { digitalwrite(a0, (channel & 1)? HIGH : LOW); digitalwrite(a1, (channel & 2)? HIGH : LOW); digitalwrite(a2, (channel & 4)? HIGH : LOW); digitalwrite(a3, (channel & 8)? HIGH : LOW); return analogread(a4);
Przetwornik analogowo-cyfrowy 8-mio kanałowy przetwornik analogowo-cyfrowy o rozdzielczości 10-cio bitowej. Kanały można skonfigurować jako niesymetryczne lub symetryczne (różnicowe). Kanałom różnicowym można przyporządkować określone wartości wzmocnienia. Typowa częstotliwość przetwarzania mieści się między 50 a 200kHz.
Rejestr ustawień ADMUX REFS1, REFS0 wybór zakresu przetwarzania ADLAR bit decydujący o sposobie wyrównania wyniku konwersji w rejestrze ADC (ADCH+ADCL), gdy ADLAR = 0 wyrównanie do prawej, gdy ADLAR = 1 wyrównanie do lewej MUX4 MUX0 wybór kombinacji wejść analogowych podłączonych do przetwornika oraz wzmocnień dla tych wejść. Dla MUX4 MUX0 = 0 wybrane jest wejście niesymetryczne 0 na porcie F ze wzmocnieniem równym 1
Zakres przetwarzania Zakres napięcia przetwarzanego może być podawany wewnętrznie lub zewnętrznie na pin AREF. Przy wyborze źródła wewnętrznego minimalne napięcie przetwarzania wynosi 0V, a maksymalne 5V-1LSB lub 2.56V-1LSB. Rozdzielczość przetwarzania jest 10-bitowa.
Wyrównanie wyniku konwersji w rejestrze danych Rejestr danych ADCH i ADCL (dla bitu ADLAR = 0) Bit 15 14 13 12 11 10 9 8 ADCH - - - - - - ADC9 ADC8 ADCL ADC7 ADC6 ADC5 ADC4 ADC3 ADC2 ADC1 ADC0 Bit 7 6 5 4 3 2 1 0 Odczyt/zapis R R R R R R R R Wartość początkowa 0 0 0 0 0 0 0 0 Rejestr danych ADCH i ADCL (dla bitu ADLAR = 1) Bit 15 14 13 12 11 10 9 8 ADCH ADC9 ADC8 ADC7 ADC6 ADC5 ADC4 ADC3 ADC2 ADCL ADC1 ADC0 - - - - - - Bit 7 6 5 4 3 2 1 0 Odczyt/zapis R R R R R R R R Wartość początkowa 0 0 0 0 0 0 0 0
Rejestr statusowy ADCSRA ADEN włączenie przetwornika ADSC rozpoczęcie przetwarzania ADC. Konwersja trwa 14 cykli zegara przetwornika, przy czym 1-sza konwersja po włączeniu przetwornika trwa 25 cykli zegara przetwornika. ADFR - włączenie ciągłego przetwarzania, rejestr wyniku przetwarzania jest aktualizowany w sposób ciągły ADIF flaga sygnalizująca zakończenie pojedynczego przetwarzania ADIE maska przerwania przetwornika ADPS2, ADPS1, ADPS0 preskaler zegara przetwornika, im większy współczynnik preskalera tym powolniejszy zegar przetwornika i dokładniejszy wynik konwersji
Czas konwersji Czas konwersji jest wyrażony w cyklach zegara przetwornika Warunki Czas uśredniania (w cyklach zegara przetwornika) Czas konwersji (w cyklach zegara przetwornika) 1-sza konwersja 14.5 25 Konwersja na wejściu niesymetrycznym Konwersja na wejściu różnicowym 1.5 13 1.5/2.5 13/14
Prescaler zegara przetwornika ADPS2 ADPS1 ADPS0 Współczynnik podziału 0 0 0 2 0 0 1 2 0 1 0 4 0 1 1 8 1 0 0 16 1 0 1 32 1 1 0 64 1 1 1 128
ADC Analog-digital converter int analogread(uint8_t pin) { uint8_t low, high; ref= 1; pin -= 14; ADMUX = (ref<< 6) (pin & 0x07); sbi(adcsra, ADEN); sbi(adcsra, ADSC); while (bit_is_set(adcsra, ADSC)); low = ADCL; high = ADCH; return (high << 8) low; int mojadc() { char l, h; ADMUX = ((1<<REFS0)); ADCSRA = ((1<<ADEN) (1<<ADSC)); ADCSRA = ((1<<ADPS2) (1<<ADPS1)); while (! (ADCSRA & (1<<ADIF))); ADCSRA = (1<<ADIF); //zerowanie flagi adif lo = ADCL; hi = ADCH; return (hi << 8) lo;
Funkcja biblioteczna int _Esplora::readSlider(byte ch) Funkcja biblioteczna boolean _Esplora::readButton(byte ch) boolean readbutton_simple(byte ch) { if (ch >= SWITCH_1 && ch <= SWITCH_4) { ch--; unsigned int val = readchannel_simple(ch); return (val > 512)? HIGH : LOW;
TMP36 temperature sensor TMP36 sensor outputs 10 millivolts per degree centigrade on the signal PIN. Measuring temperatures below freezing is possible thanks to a 500 mv offset (for example 25 degrees C = 750 mv, 0degrees C = 500mV). const int a =.; const int b =.; const int c =.; int readtemperature_simple(const byte scale) { long rawt = readchannel(ch_temperature); if (scale == DEGREES_C) { return (int)((rawt * a / b) - c); Parametry pomiaru: rozdzielczość przetwornika 1024 kroki, zakres przetwarzania - 5000mV, czułość sensora - 10mV/deg, Offset sensora - 500mV