Show Posts
Pages: 1 2 [3] 4 5 ... 7
31  Using Arduino / Microcontrollers / Re: Understanding the .hex file on: April 25, 2011, 03:12:00 pm
For example, the Sparkfun website has a tutorial for getting started with loading programs onto the microcontroller.  They supply a .zip file with a .c file and the compiled .hex file (I've added spaces to indicate the formatting described below):

:10 0000 00 0C9434000C944F00 0C944F000C944F00 4F
:10 0010 00 0C944F000C944F00 0C944F000C944F00 24
:10 0020 00 0C944F000C944F00 0C944F000C944F00 14
:10 0030 00 0C944F000C944F00 0C944F000C944F00 04
:10 0040 00 0C944F000C944F00 0C944F000C944F00 F4
:10 0050 00 0C944F000C944F00 0C944F000C944F00 E4
:10 0060 00 0C944F000C944F00 11241FBECFEFD4E0 2E
:10 0070 00 DEBFCDBF11E0A0E0 B1E0E8EFF0E002C0 EC
:10 0080 00 05900D92A030B107 D9F711E0A0E0B1E0 E2
:10 0090 00 01C01D92A030B107 E1F70C9467000C94 E9
:10 00A0 00 00008FEF84B987B9 8EEF8AB9089501C0 37
:10 00B0 00 0197009759F020E0 0000000000000000 C8
:10 00C0 00 000000002F5F2A35 99F3F6CF08958FEF D7
:10 00D0 00 84B987B98EEF8AB9 8FEF88B985B98BB9 A2
:10 00E0 00 84EF91E00E945700 18B815B81BB884EF 50
:08 00F0 00 91E00E945700F0CF DF
:00 0000 01 FF

The format of the hex file is (http://en.wikipedia.org/wiki/Intel_Hex):

Quote
# Start code, one character, an ASCII colon ':'.
# Byte count, two hex digits, a number of bytes (hex digit pairs) in the data field. 16 (0x10) or 32 (0x20) bytes of data are the usual compromise values between line length and address overhead.
# Address, four hex digits, a 16-bit address of the beginning of the memory position for the data. Limited to 64 kilobytes, the limit is worked around by specifying higher bits via additional record types. This address is big endian.
# Record type, two hex digits, 00 to 05, defining the type of the data field.
# Data, a sequence of n bytes of the data themselves, represented by 2n hex digits.
# Checksum, two hex digits


[:][Byte Count][Address][Record Type][Data][Checksum]

So, the following line of the hex file can be split like this:

[:][10] [0060] [00] [0C944F000C944F0011241FBECFEFD4E0] [2E]

Instructions are 16-bits, or 4 hex digits.
The RJMP opcode is described in the ATMEGA datasheet as : 1100 kkkk kkkk kkkk
0b'1100 = 0xC
So, an instruction that has 0xC as the first digit, implies that it is an RJMP instruction:

The data from the .hex file can be parsed into the following instructions:
0C94
4F00
0C94
4F00
1124
1FBE
CFEF  <--- This is the RJMP 0xFEF instruction.  (0xFEF = decimal 4079)
D4E0


According to the addresses specified in the .hex file, the actual program is only 0x00F8 bytes long.  I'm unsure why we're jumping 4079 bytes, when our program does not exist there.
32  Using Arduino / Microcontrollers / Re: Understanding the .hex file on: April 25, 2011, 02:38:56 pm
So then, it's likely that the first several instructions in the .hex file (and subsequently Program Memory 0x00 ... up to say 0xA0) might be instructions to jump to some high address (eg: 0x7000) where the boot loader is, run some code there, and then to jump back to some lower address (eg: 0x1000) or so to where the program actually begins?
33  Using Arduino / Microcontrollers / Understanding the .hex file on: April 25, 2011, 02:24:53 pm
Recently, I've been attempting to write a simulator for my Arduino Uno w/ ATMega328p.

I've done all the hard work as to implementing the ATMega instruction set, and defining arrays for the Data and Program Memory.  All that seems to be working fine.

I've implemented these instructions via an Intel .hex file standard, like the Arduino IDE client creates when you compile your code.  The .hex files I create by hand work just fine.  I assume that when the micro-controller powers up, it sets the program counter to 0x00, and then reads instructions from the Program Memory beginning at 0x00.  Since my .hex file begins as 0x00, this works just fine.

However, when I load a .hex file created by the Arduino IDE, the assembler instructions created don't make much sense.  It appears to be doing several ADD register instructions, and then will randomly RJMP (relative jumps) to an address near 0x7000.  There's no code down at Program Memory address 0x7000.  The program is a very small "Hello World!" style program, just to make sure it's working before I go any further.

Can anyone describe what's going on in the Arduino .hex files?  There seems to be quite a bit of Assembler overhead involved in declaring the setup() and loop() methods.  I can't see any other reason for why there's so much data in the .hex file.  Is there something funny that the Arduino does with the .hex to accommodate using the boot loader?
34  Forum 2005-2010 (read only) / Syntax & Programs / Re: Concatenate to a char array / converting integers? on: December 06, 2010, 03:58:42 pm
It depends on what type of variable you want to concatinate.  If it's an integer, it shouldn't be too difficult.  Integers are stored in memory as 2 bytes.  Each character is stored as 1 byte.  

However, the value stored in each byte contains more than 1 digit worth of information.  This is where the complexity comes in.  Rather than extracting each byte with HighByte() and LowByte() functions, you'll need to write some code that extracts each digit (0-9 for decimal values) individually.

Once you have a digit individually, it can be saved in a char or a byte variable.  The main difference between byte and char variables is that bytes are just hexidecimal numbers.  Chars are also a single-byte hexidecimal number, but chars have the understanding that the data contained in them conforms to ASCII values and represent a language character and not a number specifically.  Hence the name "char".  You'll need to make sure the digit value is saved as the ASCII representation.  A quick and dirty method is to add 48 to the decimal value of the integer, and that will give you the ASCII value for 0-9.  
35  Forum 2005-2010 (read only) / Syntax & Programs / Re: Logical Operators on: December 03, 2010, 05:28:37 pm
Pin 48?  I assume you're using the Arduino Mega then. Since the microcontroller differs on some of these boards, it'd be best if you posted the link to the datasheet for the microcontroller on your board.
36  Forum 2005-2010 (read only) / Syntax & Programs / Re: STRING of 50 NUL on: December 01, 2010, 08:03:45 pm
Remember that null is not the same as ASCII zero.

0 ASCII= 48 decimal = 30 hex
null ASCII = 0 decimal = 00 hex

Serial.print(0); will print out an ASCII zero, not a null.
Serial.write(0); *should* get you a null character.

To be sure, you could try:
Code:
char MyNullCharacter=0x00;
for (int i=0;i<50;i++)
{
Serial.print(MyNullCharacter);
}

That way, you set the character equal to hex 00, which is null for sure.
37  Forum 2005-2010 (read only) / Syntax & Programs / Re: maximum duration of unsigned long on: November 18, 2010, 12:20:02 pm
Hellsinki,

No, I do not think that the number will go to the max then then start decreasing.

Code:
timecount = micros() - startTime;

Assume that startTime = 50.  (any arbitrary non-zero number)

Code:
timecount     = micros()       -  starttime
4294967245 = 4294967295  -  50

if micros() overflows and resets to zero, the subtraction causes an underflow... resulting in a large number.  So it appears tha timecount is still counting upward.
Code:
timecount     = micros()       -  starttime
4294967246 = 0                  -  50     <--- ...46, not ...96.

at the point where micros() = 50, there is no longer and underflow during subtraction.  The result simply resets to zero.
Code:
timecount     = micros()       -  starttime
0                 = 50                -  50

So, it will always appear to count upward and then overflow back to zero.

38  Forum 2005-2010 (read only) / Syntax & Programs / Re: maximum duration of unsigned long on: November 17, 2010, 02:55:20 pm
You can easily test the behavior of the overflow.  I started near the max unsigned long value so it wouldn't take long.


Code:
void setup() {
  Serial.begin(9600);
}

unsigned long MyValue=4294967290 ;

void loop() {
  MyValue=MyValue+1;
  Serial.println(MyValue,DEC);
  delay(100);
}


And the output:

Code:
4294967292
4294967293
4294967294
4294967295
0
1
2
3
4
5


The result makes sense.  Any byte value can range from 00'x fo FF'x.  So if you add 1 to FF'x, it becomes 100'x, but that won't fit into a single byte, so we consider it overflow.  The most significant digit is truncated. so you're left with 00'x.  Overflows of unsigned integers behave this way.  They behave exactly the opposite for underflow.  It wraps from 00'x to FF'x.

Now, with signed integers, it's a bit more complicated because the numbers are stored in 2's compliment.  (You'll only notice a difference for negative numbers).  The signed variable stores the same number of total values as an unsigned variable does, but they range from -x to +x intead of the unsigned range of 0 to +2x.  When the signed integer overflows, it's essentially turning on the sign bit.  The only way to detect a signed integer overflow is to take the signs of both operands and compare them to the sign of the result.

Code:
Positive + Positive = Positive
Positive + Negative = Either, depending on the magnitude of the operands.
Negative + Negative = Negative
Negative + Positive = Either, depending on the magnitude of the operands.


In your case, When micros() overflows, it resets to zero.

Code:
timecount=micros() - startTime;

When you run your program, it will look like timecount increases from zero to 4294967295-startTime.  At which point mills() overflows and resets to zero.  Zero-startTime underflows and results in a large number.  So timecount appears to keep counting upward until it reaches it's max value of 4294967295 and resets to zero.  At the point that timecount resets to zero, mills() = startTime again.

Once mills() is greater than startTime again, it will act as it did when it first started.

Essentially, it will loop from 0 to 4294967295 counting up over and over again.
39  Forum 2005-2010 (read only) / Interfacing / Re: 7-Segment Display Wiring and Programming on: December 08, 2010, 05:25:12 pm
Quote
How would I wire it with a shift register and which should I use?

Here's a shift register from Sparkfun... costs about $1.50
http://www.sparkfun.com/products/733

Read the datasheet on it and it will explain how to use it.

Basically, you connect it to the serial connection on your board, and then supply it with power and ground.  Each time you send a byte on the serial connection, it shifts it into the register (1 byte = 8 bits).  Until you send it another byte, those 8 bits will remain set.  So, you just send a byte representing the digital outputs you want to turn on/off.

Code:
Hex       Binary
0xFF = 11111111       This turns all 8 outputs of the shift register on.
0x00 = 00000000       This turns all 8 outputs of the shift register off.
0xAA = 10101010       This turns every-other output on.

So, now, all you have to do is connect each of the 8 shift register outputs to one of the segments on your display.  (Remember to connect the display to ground as well.)
40  Forum 2005-2010 (read only) / Interfacing / Re: 7-Segment Display Wiring and Programming on: December 06, 2010, 03:43:53 pm
7 Segment displays are fairly easy.

You'll need 7 I/O pins for each digit if you do it without an additional components.

Otherwise, pick up a shift register from Sparkfun.  You can then drop the I/O requirements significantly.

The datasheet shows that each of the seven segments on the display are labeled as a,b,c,d,e,f,g and dp (decimal point).  Apply a voltage to pin 1 or 5, and the apply a voltage to the pin for the segment which you want to turn on.  Pretty easy.

The trickier part will be wiring up your shift registers correctly, as you'll have a mess of wires for 8 digits (8x7 = 56 wires minimum).

You'll likely need to write some code that extracts a single decimal digit from an integer and figures out which display it goes on.
41  Forum 2005-2010 (read only) / Interfacing / Re: how to talk with VB and know the data? on: December 01, 2010, 07:49:05 pm
Use the Mid() function in VB to extract the value you want from the string.

Remember that Visual Basic will interpret all incoming serial data to ASCII.  You must be careful that if you want to send ASCII digits, use the print(range,DEC).  That may be the default for integers and doubles, but it won't be for anything stored in raw BYTE data.
42  Forum 2005-2010 (read only) / Interfacing / Re: Reading Arduino data with C++ program on: December 02, 2010, 12:27:19 pm
Can you post a sample of the (incorrect) data received by your C++ program?
43  Forum 2005-2010 (read only) / Interfacing / Re: Basic software architecture for LED on: November 25, 2010, 11:59:12 am
Quote
What I'm not sure about is how quickly I'll need to sample in order to get a good idea of when the beat is.

Depends on the sampling rate of the music you're listening to.  Google "Nyquist Frequency".  Basically, Nyquist says to only sample at 1/2 the frequency.  If the music was converted to digital, then it's already been sampled, so there's no reason for checking more rapidly than the sampling of the music already.  (ie:  You won't get any more data resolution out of it... you start overlapping and only sample extra noise into the mix).  If you're dealing with analog music, then check out the range of sampling that most mp3's are recorded at.  8khz is about as slow as music sampling goes.  Any less than that, it sounds absolutely terrible.  Most mp3's are sampled at 128kHz, I don't notice any improvement above that, although I'm not an audio professional.  Read the wikipedia article, it's quite good.
44  Forum 2005-2010 (read only) / Interfacing / Re: Visual Basic, Firmata and Arduino on: November 16, 2010, 06:45:21 pm
You'll have a large difficulty getting VB to upload code to the Arduino.  Sending data and communicating with a sketch already uploaded to the board is quite easy.  You need to put a MSComm control on your form.  You'll find that in the list of components as "Microsoft Comm Control"  Once you have that, it's quite easy, just read the MSDN about the Comm control if you don't see how to do it from there.
45  Forum 2005-2010 (read only) / Interfacing / Re: Visual Basic for Arduino on: November 19, 2010, 11:56:48 am
To se it to com14, just set
Code:
form1.MSComm1.CommPort=14
.
Pages: 1 2 [3] 4 5 ... 7