Category Archives: electronics

External interrupts on Atmega 328

It’s this simple:


pinMode(5,INPUT);
PCMSK2 |= (1< PCICR |= (1 << PCIE2); // set PCIE2 to PCMSK2 scan

--
Catch the interrupts (default when signal goes up OR down)

ISR(PCINT2_vect)
{
// code here..
}

PCINT?_vect vectors are always used for Pin Change Interrupt Request Interrupts (see http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html)

--
Remember:

PCINT0..7 are asscociated with the 8 pins in PORTA and trigger the PCINT0_vect interrupt
PCINT8..15 are asscociated with the 8 pins in PORTB and trigger the PCINT1_vect interrupt
PCINT16..23 are asscociated with the 8 pins in PORTC and trigger the PCINT2_vect interrupt
PCINT24..31 are asscociated with the 8 pins in PORTD and trigger the PCINT3_vect interrupt

Problems flashing Turnigy 9X with USBTiny?

I couldn’t flash my Turnigy 9X with Ladyada’s USBTinyISP (ver 2) until I found a solution

“I think you will find that your Device signature = 0x000000 problem is shared between the programmer and the Turnigy 9x. The Ladyada USB (known to avrdude as usbtiny) programmer schematic shows 1k5 short circuit protection resistors in the SCK and MOSI programming lines. I suspect that your programmer has the same circuit. The Turnigy 9X has 200R and .1uF capaitors on these lines to debounce the button inputs to the ATMega64. Unfortunately the debounce circuit slows down the programming pulses and prevents programming. Reducing the two 1k5 resistor values in the programmer to 100R fixes the problem, but so does choosing a different programmer!
I tried slowing down the programmer with -B option, but could not get the pulses slow enough.”

Source: http://diydrones.com/forum/topics/turnigy-9x-flashing-problem

Changed those resistors to 100 ohm and flashing worked. However first write failed the read verification set but retry gave 100% correct.

Good source: http://code.google.com/p/th9x/wiki/installation_de?wl=en-GB

Arduino & millis() – overflow

We know that the value of millis() rolls over after 49 days. You can write a hack to overcome with this but how to make sure it works, without testing your code for 49 days?

Here’s the trick. Modify the arduino core code so that millis() will actually roll over after 10 seconds from start. If your Arduino program overcomes that, it will probably do it again after 49 days.

Edit file /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/wiring.c

.. And modify / replace:
#include
volatile unsigned long timer0_millis = ULONG_MAX - (1000*10);

Better colors for Arduino IDE

With just small changes you can make Arduino IDE better for your eyes. Try this, change theme.txt that is located in /Applications/Arduino.app/Contents/Resources/Java/lib/theme, dunno about Windows.

# GUI – STATUS
status.notice.fgcolor = #000000
status.notice.bgcolor = #54919e
status.error.fgcolor = #ffffff
status.error.bgcolor = #662000
status.edit.fgcolor = #000000
status.edit.bgcolor = #cc9900
status.font = SansSerif,plain,12

# GUI – TABS
# settings for the tabs at the top
# (tab images are stored in the lib/theme folder)
header.bgcolor = #216886
header.text.selected.color = #1a1a00
header.text.unselected.color = #ffffff
header.text.font = SansSerif,plain,12

# GUI – CONSOLE
console.font = Monospaced,plain,11
console.font.macosx = Monaco,plain,10
console.color = #000000
console.output.color = #cccccc
console.error.color = #ff3000

# GUI – BUTTONS
buttons.bgcolor = #044f6f
buttons.status.font = SansSerif,plain,12
buttons.status.color = #ffffff

# GUI – LINESTATUS
linestatus.color = #ffffff
linestatus.bgcolor = #044f6f

# EDITOR – DETAILS

# foreground and background colors
editor.fgcolor = #ffffff
editor.bgcolor = #000000

# highlight for the current line
editor.linehighlight.color=#005500
# highlight for the current line
editor.linehighlight=true

# caret blinking and caret color
editor.caret.color = #FF00FF

# color to be used for background when ‘external editor’ enabled
editor.external.bgcolor = #c8d2dc

# selection color
editor.selection.color = #888888

# area that’s not in use by the text (replaced with tildes)
editor.invalid.style = #7e7e7e,bold

# little pooties at the end of lines that show where they finish
editor.eolmarkers = false
editor.eolmarkers.color = #999999

# bracket/brace highlighting
editor.brackethighlight = true
editor.brackethighlight.color = #FF0000

# TEXT – KEYWORDS

# e.g abstract, final, private
editor.keyword1.style = #00FFFF,plain

# e.g. beginShape, point, line
editor.keyword2.style = #00FFFF,plain

# e.g. byte, char, short, color
editor.keyword3.style = #FF00FF,bold

# TEXT – LITERALS

# constants: e.g. null, true, this, RGB, TWO_PI
editor.literal1.style = #5599CC,plain

# p5 built in variables: e.g. mouseX, width, pixels
editor.literal2.style = #00FFFF,plain

# e.g. + – = /
editor.operator.style = #00FFFF,plain

# ?? maybe this is for words followed by a colon
# like in case statements or goto
editor.label.style = #7e7e7e,bold

# TEXT – COMMENTS
editor.comment1.style = #7e7e7e,plain
editor.comment2.style = #7e7e7e,plain

# LINE STATUS – editor line number status bar at the bottom of the screen
linestatus.font = SansSerif,plain,10
linestatus.height = 20

BenQ M23 loosing network

If your BenQ M23 GSM module is losing network or doesn’t stay in the network you might have to register it to network with command:

AT+COPS=1,2,”24405″

Where 24405 is the “numeric format is the GSM Location Area Identification number which consists of a three BCD digit country code coded as in ITU-T E.212 Annex A[10], plus a two BCD digit network code, which is administration specific”.

You can get LAC number by commanding:

AT+COPS=?

(and wait for 10 seconds or so..)

433 MHz receiver and NewSoftSerial

If you’re having problem with NewSoftSerial versus SoftwareSerial when using 434 MHz (433.92MHz) – receiver, it’s because the receiver cannot pull down the RX pin on your arduino. The library changes the input pin to be pull-up when non-inversion is used.

Change the library in following manner:

NewSoftSerial.cpp:

void NewSoftSerial::setRX(uint8_t rx)
{
pinMode(rx, INPUT);
/*
if (!_inverse_logic)
digitalWrite(rx, HIGH); // pullup for normal logic!
*/
_receivePin = rx;
_receiveBitMask = digitalPinToBitMask(rx);
uint8_t port = digitalPinToPort(rx);
_receivePortRegister = portInputRegister(port);
}

More info :

http://arduiniana.org/libraries/newsoftserial/
http://www.sparkfun.com/commerce/product_info.php?products_id=8950

Working: XBee 2.5

Communicating between two XBee 2.5’s quick instructions:

– XBee is very versatile radio modem which works trough serial connection. It’s really simple when you get it working; everything you send to the XBee Serial port is coming out of other XBee serial port. That’s it. And it works on 2.4 gig frequency. It’s very very the same as old modems that were used trough telephones. Here, just replace the telephone line with built-in 2.4 GHz support.
– However you have to configure the 2.5 version first to get things right. It doesn’t work out of the box!
– You *NEED* to use the X-CTU and configure other as ZNET 2.5 COORDINATOR AT (“master”)and the other as ZNET 2.5 ROUTER/END DEVICE AT (node).
– Make sure XBee answers to +++ command. If it doesn’t work your communication is not working, probably your COM speed is incorrect.
– You *MUST* dial from the master to node with the ATDN command. Otherwise it’s in broadcast mode and it’s unreliable. However the communcation works in broadcast but in broadcast you might also loose the connection quite easily. If the master is rebooted it might not connect automatically to node in broadcast.
– PAN ID is your network ID, this must be the same between all devices that communicate together
– Arduino Fio cannot be programmed when XBee is connected (same Serial line)
– You can use the SparkFun XBee shield together with FTDI adapter to program the XBee with X-CTU. Just connect Serial (3.3V level!!) and VCC (3.3!!) and GND. XBee doesn’t need anything else. Of course disconnect the Arduino board from the shield so that you don’t connect the two serial lines together :)

These instructions really helped me: http://t413.com/news/fast-2-way-xbee-series-2-data

Thanks to SparkFun again for great products and support.

Some links:

http://www.sparkfun.com/commerce/product_info.php?products_id=9588
http://www.sparkfun.com/commerce/product_info.php?products_id=8691

BMP085 with Arduino (tested & working)

I tested & corrected and this code really works.


// BMP08 with Arduino

// DANGER: The BMP08 accepts 1.8 to 3.6 Volts – so no chance to connect it directly to 5 Volts.

// Connect VCC to VCC and GND to GND, SCL goes to analogue pin 5, SDA to analogue pin4.
// Notice! Sparkfun breakoutboard contains already 4.7K pull ups,
// If not using pre-built pull-ups:
// --> Add some pull up resistors (1K to 20K, most often something like 4.7K) between SDA, SCL and VCC finishes the setup.

// References: http://interactive-matter.org/2009/12/arduino-barometric-pressure-sensor-bmp085/ and http://news.jeelabs.org/2009/02/19/hooking-up-a-bmp085-sensor/
// Specification: http://www.bosch-sensortec.com/content/language1/downloads/BST-BMP085-DS000-05.pdf
// SparkFun breakout board: http://www.sparkfun.com/commerce/product_info.php?products_id=9694

#include "Wire.h"

#define I2C_ADDRESS 0x77

const unsigned char oversampling_setting = 3; //oversamplig for measurement
const unsigned char pressure_waittime[4] = { 5, 8, 14, 26 };

//just taken from the BMP085 datasheet
int ac1;
int ac2;
int ac3;
unsigned int ac4;
unsigned int ac5;
unsigned int ac6;
int b1;
int b2;
int mb;
int mc;
int md;

void setup()
{
Serial.begin(9600); // start serial for output
Serial.println("Setting up BMP085");
Wire.begin();
bmp085_get_cal_data();
}
void bmp085_read_temperature_and_pressure(int& temperature, long& pressure);
void loop()
{
int temperature = 0;
long pressure = 0;

bmp085_read_temperature_and_pressure(&temperature,&pressure);
Serial.print(temperature,DEC);
Serial.print(" ");
Serial.print(pressure,DEC);
Serial.println();
delay(100);
}

void bmp085_read_temperature_and_pressure(int* temperature, long* pressure) {
int ut= bmp085_read_ut();
long up = bmp085_read_up();
long x1, x2, x3, b3, b5, b6, p;
unsigned long b4, b7;

//calculate the temperature
x1 = ((long)ut - ac6) * ac5 >> 15;
x2 = ((long) mc << 11) / (x1 + md);
b5 = x1 + x2;
*temperature = (b5 + 8) >> 4;

//calculate the pressure
b6 = b5 - 4000;
x1 = (b2 * (b6 * b6 >> 12)) >> 11;
x2 = ac2 * b6 >> 11;
x3 = x1 + x2;

//b3 = (((int32_t) ac1 * 4 + x3)<> 2;

if (oversampling_setting == 3) b3 = ((int32_t) ac1 * 4 + x3 + 2) << 1;
if (oversampling_setting == 2) b3 = ((int32_t) ac1 * 4 + x3 + 2);
if (oversampling_setting == 1) b3 = ((int32_t) ac1 * 4 + x3 + 2) >> 1;
if (oversampling_setting == 0) b3 = ((int32_t) ac1 * 4 + x3 + 2) >> 2;

x1 = ac3 * b6 >> 13;
x2 = (b1 * (b6 * b6 >> 12)) >> 16;
x3 = ((x1 + x2) + 2) >> 2;
b4 = (ac4 * (uint32_t) (x3 + 32768)) >> 15;
b7 = ((uint32_t) up - b3) * (50000 >> oversampling_setting);
p = b7 < 0x80000000 ? (b7 * 2) / b4 : (b7 / b4) * 2;

x1 = (p >> 8) * (p >> 8);
x1 = (x1 * 3038) >> 16;
x2 = (-7357 * p) >> 16;
*pressure = p + ((x1 + x2 + 3791) >> 4);

}

unsigned int bmp085_read_ut() {
write_register(0xf4,0x2e);
delay(5); //longer than 4.5 ms
return read_int_register(0xf6);
}

void bmp085_get_cal_data() {
Serial.println("Reading Calibration Data");
ac1 = read_int_register(0xAA);
Serial.print("AC1: ");
Serial.println(ac1,DEC);
ac2 = read_int_register(0xAC);
Serial.print("AC2: ");
Serial.println(ac2,DEC);
ac3 = read_int_register(0xAE);
Serial.print("AC3: ");
Serial.println(ac3,DEC);
ac4 = read_int_register(0xB0);
Serial.print("AC4: ");
Serial.println(ac4,DEC);
ac5 = read_int_register(0xB2);
Serial.print("AC5: ");
Serial.println(ac5,DEC);
ac6 = read_int_register(0xB4);
Serial.print("AC6: ");
Serial.println(ac6,DEC);
b1 = read_int_register(0xB6);
Serial.print("B1: ");
Serial.println(b1,DEC);
b2 = read_int_register(0xB8);
Serial.print("B2: ");
Serial.println(b1,DEC);
mb = read_int_register(0xBA);
Serial.print("MB: ");
Serial.println(mb,DEC);
mc = read_int_register(0xBC);
Serial.print("MC: ");
Serial.println(mc,DEC);
md = read_int_register(0xBE);
Serial.print("MD: ");
Serial.println(md,DEC);
}

long bmp085_read_up() {
write_register(0xf4,0x34+(oversampling_setting<<6));
delay(pressure_waittime[oversampling_setting]);

unsigned char msb, lsb, xlsb;
Wire.beginTransmission(I2C_ADDRESS);
Wire.send(0xf6); // register to read
Wire.endTransmission();

Wire.requestFrom(I2C_ADDRESS, 3); // read a byte
while(!Wire.available()) {
// waiting
}
msb = Wire.receive();
while(!Wire.available()) {
// waiting
}
lsb |= Wire.receive();
while(!Wire.available()) {
// waiting
}
xlsb |= Wire.receive();
return (((long)msb<<16) | ((long)lsb<<8) | ((long)xlsb)) >>(8-oversampling_setting);
}

void write_register(unsigned char r, unsigned char v)
{
Wire.beginTransmission(I2C_ADDRESS);
Wire.send(r);
Wire.send(v);
Wire.endTransmission();
}

char read_register(unsigned char r)
{
unsigned char v;
Wire.beginTransmission(I2C_ADDRESS);
Wire.send(r); // register to read
Wire.endTransmission();

Wire.requestFrom(I2C_ADDRESS, 1); // read a byte
while(!Wire.available()) {
// waiting
}
v = Wire.receive();
return v;
}

int read_int_register(unsigned char r)
{
unsigned char msb, lsb;
Wire.beginTransmission(I2C_ADDRESS);
Wire.send(r); // register to read
Wire.endTransmission();

Wire.requestFrom(I2C_ADDRESS, 2); // read a byte
while(!Wire.available()) {
// waiting
}
msb = Wire.receive();
while(!Wire.available()) {
// waiting
}
lsb = Wire.receive();
return (((int)msb<<8) | ((int)lsb));
}

Links: http://sensorapp.net/?p=278