but as soon as i change 900 to -900 i get the result as 64636. I'm sure there must be a simple solution for this but my search of the forum and google only led me to the second method i showed above and it doesn't work either.
I recently asked about converting a signed int to bytes and the answer i got here worked a charm! I am now considering doing the same with signed longs but expanding the method doesn't appear to be working for me!
Have a look at these two functions that I use for writing or reading any value from EEPROM. It works with floats, longs, bytes, chars, and even custom types like structs and class instances.
Delta_G this looks like it could save me allot of time! I will have a look into it now
Nick I had a look at the article and from what i could tell i needed to try this (it didn't work)
Ok so trying the Unions ( something i am going to have to read up on! - only learnt programming through using arudino so i'm getting their slowly) I get this error
error: 'T' has not been declared
Also this still doesn't seem to work - sorry for being so thick sculled here! prints out -7616
Ok so fixed this (forgot to include the template in the header file as well. Now i get this problem XD
D:\Users\Dropbox\Arduino\libraries\SpiRam_Extended\SpiRam_Extended.cpp: In function 'int writeTest(long int, T&)':
D:\Users\Dropbox\Arduino\libraries\SpiRam_Extended\SpiRam_Extended.cpp:195:37: error: there are no arguments to '_prepare' that depend on a template parameter, so a declaration of '_prepare' must be available [-fpermissive]
D:\Users\Dropbox\Arduino\libraries\SpiRam_Extended\SpiRam_Extended.cpp:195:37: note: (if you use '-fpermissive', G++ will accept your code, but allowing the use of an undeclared name is deprecated)
D:\Users\Dropbox\Arduino\libraries\SpiRam_Extended\SpiRam_Extended.cpp: In function 'int readTest(long int, T&)':
D:\Users\Dropbox\Arduino\libraries\SpiRam_Extended\SpiRam_Extended.cpp:213:36: error: there are no arguments to '_prepare' that depend on a template parameter, so a declaration of '_prepare' must be available [-fpermissive]
Ah sorry the stuff i quoted above was trying to fix the shifting method
cpp file
template<class T>
int writeTest(long address, T& value)
{
union {
T type;
byte b[sizeof(T)];
}
temp;
temp.type = value;
_prepare(STREAM_MODE,WRITE,address);
for (unsigned int i = 0; i < sizeof(T); i++)
{
SPI.transfer(address + i, temp.b[i]);
}
return sizeof(T);
}
template<class T>
int readTest(long address, T& value)
{
union {
T type;
byte b[sizeof(T)];
}
temp;
_prepare(STREAM_MODE,READ,address);
for (unsigned int i = 0; i < sizeof(T); i++)
{
temp.b[i] = SPI.transfer(0xFF);
}
value = temp.type;
return sizeof(T);
}
header file
template<class T>
int writeTest(long address, T& value);
template<class T>
int readTest(long address, T& value);
void setup ()
{
Serial.begin (115200);
Serial.println ();
typedef union {
long num;
byte b [sizeof(long)];
} myUnion;
myUnion foo;
foo.num = 123456;
for (int i = 0; i < sizeof (long); i++)
Serial.println ((int) foo.b [i]);
// make another one
myUnion bar;
// copy each byte in
for (int i = 0; i < sizeof (long); i++)
bar.b [i] = foo.b [i];
// print the resulting long
Serial.println (bar.num);
} // end of setup
void loop () { }
I tried this and it works on my Teensy 3.1 - I'm gonna head to bed now but I will look into it more tomorrow and try to apply what you have shown me in this demo script to the library!
I'm sorry if this post is beside the point, as I quickly glanced over the posts rather than reading them.
The problem is sending multiple-byte-values over a serial interface that works on a per-byte basis. Obviously, longer types are stored as bytes, so all you need to do is take its address and convert this to a byte*. The union approach does the trick but seems a little verbose. Why not use reinterpret_cast?
long val = 0x89abcdef; // 4 bytes!
Serial.write(reinterpret_cast<byte*>(&val), sizeof(val));
Just keep in mind you might have to compensate for endianness when putting it back together at the other end of the line. Probably that's not even necessary.
PS. Code not tested so could contain errors. I hope the idea is clear though.
Edit: By the way, this works for any type (floats, doubles, user-defined types, whatever). If you want, you can make it a (very simple, not scary at all) template:
The OP did not specifically mention sending the data anywhere (although you might guess that is his/her intention).
There are already templated functions that simplify doing that, plus what you (jorenheit) suggest. I would be worried a bit about sending raw data down the serial port. For one thing, the 0x00 bytes might be treated as the end of the data stream.
For one thing, the 0x00 bytes might be treated as the end of the data stream.
Whether or not 0x00 bytes are treated as delimiters depends on the receiver implementation. I have done exactly this. The data I was sending could be anything, so it wouldn't be safe to define a delimiter at all. What else would you think is wrong with communicating data like this?
Speaking for myself, I considered plain ascii, but that would simply bloat the data too much (1 byte per digit). On top of that, it requires pre- and post-processing if used for anything else besides displaying.
Implementing a protocol like you suggest would definately help verify the integrity of the data. You'd have to have multiple-byte header- and footer-codes to minimize the chance of collisions though. How many would be sufficient depends on the problem. However... I think at this point we're back at square 1. What if one of the control-bytes gets lost for whatever reason?
Another option would be to let the first 4 bytes hold the number of elements, such that the receiver can just wait for that number to show up (and implement some time-out).
In the end, you're still in need of a way of converting the data to raw bytes so the cast I suggested is still valid I think.