Arduino controlled wheelchair

Power wheelchair board for REAL info!

POWERCHAIR MENU! www.wheelchairdriver.com/powerchair-stuff.htm

Re: Arduino controlled wheelchair

Postby gcebiker » 09 Feb 2016, 04:54

Its not responding to second packet,...trying to track it down.
http://greenmobility.com.au/rc-wheelchair-controller/
My YouTube Ch -- https://www.youtube.com/user/gcebiker
User avatar
gcebiker
 
Posts: 879
Joined: 11 Jul 2015, 14:20
Location: Gold Coast, Queensland, Australia.

Re: Arduino controlled wheelchair

Postby gcebiker » 10 Feb 2016, 14:26

Base now responding to full start up packets, found noise issue, DG419 was slightly under powered and causing noise on H side of Async lines.

Still a work in progress....but as far as i know...First in the world with FULL SCALE Arduino emulation of stock joystick for this chair.
...for certain the first brain damaged hacker to do it to his own chair.

This was a two second capture and all with responses from base !
Image
http://greenmobility.com.au/rc-wheelchair-controller/
My YouTube Ch -- https://www.youtube.com/user/gcebiker
User avatar
gcebiker
 
Posts: 879
Joined: 11 Jul 2015, 14:20
Location: Gold Coast, Queensland, Australia.

Re: Arduino controlled wheelchair

Postby gcebiker » 10 Feb 2016, 14:34

If my Robot vacuum can have 'drop off' sensors 'wall sensors' and 'roof mapping' ...and a web camera...

Why cant my dumb power chair ?

This intended to be an add on module to enhance the function and safety of your power chair.

Once a DIY Arduino can do it, there is no need to refit a new Power motor driver.

Robot wars just got cheaper :)

Waiting on some Digi Spark Pro's http://digistump.com/products/109
and more MAX485's

Then also begin to interface Nintendo Wii, wired and wireless into the project.
and a RF24 version.
http://greenmobility.com.au/rc-wheelchair-controller/
My YouTube Ch -- https://www.youtube.com/user/gcebiker
User avatar
gcebiker
 
Posts: 879
Joined: 11 Jul 2015, 14:20
Location: Gold Coast, Queensland, Australia.

Re: Arduino controlled wheelchair

Postby gcebiker » 11 Feb 2016, 06:20

DougL of course has already done this for the Jazzy Select GT....

Jim did it with a RoboBoard,

Gizmo Smith did a lot of ground work but moved on to other things.

..and that guy on YouTube did something like this with a laptop strapped to the chair.

I still feel pretty good about getting this far, i am learning as i go, each small success is very satisfying.
http://greenmobility.com.au/rc-wheelchair-controller/
My YouTube Ch -- https://www.youtube.com/user/gcebiker
User avatar
gcebiker
 
Posts: 879
Joined: 11 Jul 2015, 14:20
Location: Gold Coast, Queensland, Australia.

Re: Arduino controlled wheelchair

Postby gcebiker » 13 Feb 2016, 10:03

Doug or Lenny or Woody....

does anyone know how to properly write the check sum for Data [9] ?
...at least i think that is the checksum byte....

I tried to use your version Doug but i must have something wrong.

The correct result of the sum would be '141'

I guess its not straight math ?
Ive tried a good while to figure it out but as i dont know what i am doing, looking for what i am doing wrong is not working out to well...

Any pointers would be appreciated.
Its taken me hours and hours to realize why the code works when i write fixed values but stops working the minute i move the joystick.. :oops:
Code: Select all
 {
    //build serial packet
    data[0] = (0x74);   // start identifier. " t "
    data[1] = (130);      // Joystick speed
    data[2] = (133);      // Joystick direction
    data[3] = (130);      // Max speed setting via turtle/hare buttons on joystick?
    data[4] = (128);      // Speed Fine Tune ?
    data[5] = (136);      // default horn off, horn on value is 130
    data[6] = (205);      //data[6] = 205;      // joystick On Value ?
    data[7] = (160);      //data[7] = 160;      // chair mode/ drive 128, tilt/aux output 129
    data[8] = (128);      //data[8] = 128;      //not used?
    data[9] = 0xff - (data[0] + data[1] + data[2] + data[3] + data[4] + data[5] + data[6] + data[7] + data[8]);       //-Checksum expected result   data[9] = (141);
    data[10] = (15);      //data[10] = 15;      // all packets end with this identifier



    for (unsigned char i = 0; i < 11; i++)
      sharkSerial.write(data[i]);

  }


Just realized i have 0xff instead of 0x0F not sure what else i am doing wrong.
http://greenmobility.com.au/rc-wheelchair-controller/
My YouTube Ch -- https://www.youtube.com/user/gcebiker
User avatar
gcebiker
 
Posts: 879
Joined: 11 Jul 2015, 14:20
Location: Gold Coast, Queensland, Australia.

Re: Arduino controlled wheelchair

Postby LROBBINS » 13 Feb 2016, 11:00

I have played with this only a very little bit, but I have a suspicion that you are running into a problem of overflowing a byte (unsigned 8-bit number).

First, I'm assuming that your array is declared as byte data[10], but when you the sum you are trying to put in data[9] (before the subtraction) is 1266 which will not fit into a byte, indeed it is rolling over more than once as the numbers are added. So the first thing I would do is remove data[9] from your byte array by declaring an integer variable:

Code: Select all
int DataSum = 0;
for (byte i = 0, i<=8, i++){
  DataSum = DataSum + Data[i];
}

and compare that to what you expect for your checksum. Also, how have you decided that the check sum should be "141"? Perhaps it should also be an integer rather than a byte.

Second, if the message structure is similar to CAN, there are only 8 bytes of data and your data[0] = "start identifier" might either be the ID field (or something else entirely). If it's the message ID, and CAN-like, it is masked and filtered by the receiving node before ever calculating the checksum. Hence, only the 8 data bytes should be summed. (BTW, the standard CAN message ID is 11 bits long, many of which could obviously be 0, but they could sometimes all be filled so you could have an overflow cramming that into a byte as well.)

Third, CAN does not include a simple checksum in its message, but a 15-bit long CRC field. Could it be that the Shark's protocol also uses a circular redundancy check rather than checksum? From Wikipedia:
A cyclic redundancy check (CRC) is an error-detecting code commonly used in digital networks and storage devices to detect accidental changes to raw data. Blocks of data entering these systems get a short check value attached, based on the remainder of a polynomial division of their contents. On retrieval, the calculation is repeated and, in the event the check values do not match, corrective action can be taken against data corruption.
CRCs are so called because the check (data verification) value is a redundancy (it expands the message without adding information) and the algorithm is based on cyclic codes. CRCs are popular because they are simple to implement in binary hardware, easy to analyze mathematically, and particularly good at detecting common errors caused by noise in transmission channels. Because the check value has a fixed length, the function that generates it is occasionally used as a hash function.

Note that the fixed length of a CRC is a great convenience compared to the variable length of a sum even though the calculation is more complex: the total length of the message packet is always the same without needing extra padding in different messages. An aside: in CAN, all nodes, even those for whom the message is going to be ignored because its ID is filtered out, do calculate the CRC and send an "error" return if it's bad. This will cause the sending node to re-transmit if ANY node says the message has been corrupted. Another reason why CAN is such a robust protocol for critical environments.

Hope this helps, though certainly I'm not sure that it will.

Ciao,
Lenny
LROBBINS
 
Posts: 5789
Joined: 27 Aug 2010, 09:36
Location: Siena, Italy

Re: Arduino controlled wheelchair

Postby gcebiker » 13 Feb 2016, 11:11

Hi Lenny i will pm you.
http://greenmobility.com.au/rc-wheelchair-controller/
My YouTube Ch -- https://www.youtube.com/user/gcebiker
User avatar
gcebiker
 
Posts: 879
Joined: 11 Jul 2015, 14:20
Location: Gold Coast, Queensland, Australia.

Re: Arduino controlled wheelchair

Postby gcebiker » 13 Feb 2016, 11:28

Short excerpt

Data shall be sent in packet on the Shark Bus. Packets shall consist of a start byte, which includes the type of the packet and its length, followed by the data, followed by a check sum, The exception to this is the "Transmit Finished" packet , which shall be a single, fixed value byte.


I forgot about the check sum and was just writing what i captured, today i remembered the check sum part and figured out why, ....as long as i did not move the joystick, the emulator worked.

As soon as i moved the joystick , the check sum was changing and thus the Shark Power Base stopped responding to invalid data.
http://greenmobility.com.au/rc-wheelchair-controller/
My YouTube Ch -- https://www.youtube.com/user/gcebiker
User avatar
gcebiker
 
Posts: 879
Joined: 11 Jul 2015, 14:20
Location: Gold Coast, Queensland, Australia.

Re: Arduino controlled wheelchair

Postby gcebiker » 13 Feb 2016, 13:40

gcebiker wrote:Short excerpt
As soon as i moved the joystick , the check sum was changing and thus the Shark Power Base stopped responding to invalid data.


Gomen, it was the fixed Check Sum causing the problem

I had a fixed value for the Check Sum, instead of the 'calculated' value.
Hence the emulator worked while i had a direct write of captured data.

...but failed when i tried moving the emulators Joystick inputs.
Because data[checksum] did not equal data[values]

Sorry i am operating on RAW brain energy atm, tying shoelaces is so hard i went to thongs, not an option when coding...
http://greenmobility.com.au/rc-wheelchair-controller/
My YouTube Ch -- https://www.youtube.com/user/gcebiker
User avatar
gcebiker
 
Posts: 879
Joined: 11 Jul 2015, 14:20
Location: Gold Coast, Queensland, Australia.

Re: Arduino controlled wheelchair

Postby LROBBINS » 13 Feb 2016, 17:29

Hi Tony,

Thanks for sending me the Shark communications spec document. I have no idea why Dynamic re-invented the wheel for this, but it is definitely their own protocol that is similar to CAN but has quite a bit removed. The checksum byte is indeed a checksum and not a CRC. Its definition is:
Finally all packets except for the Transmit Finished packet shall include a one-byte checksum, which is defined as 0x7F - ( least-significant 7 bits of ( sum of all data bytes and start byte ) ).


The check sum does indeed include the start byte (that byte serves the same role as the ID field in CANbus, but is only 1 byte rather than 11 bits long), so you are correct that you have to sum 9 bytes if the packet has 8 data bytes. Actually, the information is actually contained in only bits 0 to 6 of each byte, with bit 7 set to 0 in the start byte and 1 in the data bytes. Different packets, however, have different numbers of data bytes, and you have to sum only those. The length information is in the start byte, and you will have to do some bitwise operations to extract the three bits that contain the length:
The first, or start, byte of a packet defines its type and the length of the data that it contains. The type is in bits 3-0, and the length is in bits 6-4. This allows for 16 packet types, each containing up to 8 bytes of data (the length field does not include the start byte nor the checksum). Note that the number in the length field is one less than the data length: 000 = 1 data byte, 111 = 8 data bytes. The "Transmit Finished" byte is an exception to this, as it has a length field of 000 but has zero data bytes and no checksum.

Only after you ignore the packet if it is a "Transmit Finished" message, and find the number of data bytes, you can find the check sum. However, you have to put that sum in an integer (NOT a byte) and then extract the 7 least significant bits of that and subtract that result from 0x7F (=0b01111111, notice that this 7 bits of a byte, just as for the data bytes themselves.) So again, you will have to do a bitwise manipulation on that integer sum. A bitwise AND with 0b01111111 with the result cast to a byte will get rid everything except the 7 least significant bits. It may be easier to see what's happening, and tell whether you are coming up with the correct number, if you write all your values with binary representation - and in Arduino you can Serial.print the binary by doing:
Code: Select all
Serial.print ("0b");
Serial.print (variable, BIN);

Data[] could always contain 9 bytes, and you just fill the ones you need with incoming data, if before interpreting each message you set all the Data[i] to 0. Doing this, you can sum all 9 even if there's, for example, only a start byte and 1 data byte, but you have to make sure none of the Data[i] contain a number from a previous message.

In what I just wrote I assumed that they are summing all 8 bits of each byte, including bit 7 as they just say it's the "sum of all bytes", but I wouldn't be surprised if they are actually extracting and summing just bits 0 through 6 and got sloppy in the wording. If that's the case, you'll end up having to bitwise mask each byte (bitwise AND with 0b01111111) to get rid of the topmost bit before summing.

Ciao,
Lenny
LROBBINS
 
Posts: 5789
Joined: 27 Aug 2010, 09:36
Location: Siena, Italy

Re: Arduino controlled wheelchair

Postby gcebiker » 14 Feb 2016, 14:59

...i think my brain is going to explode, but its starting to make some sense....like chopping a 16bit piece of data into half and excluding the first bit ?

Tried to understand this stuff http://playground.arduino.cc/Code/BitMath helped a little bit.

So for the SR packets to calculate the checksum it would be ?

Code: Select all
data[8] = (0x7F) - (Lsb7 - (data[0] + data[1] + data[2] + data[3] + data[4] + data[5] + data[6] + data[7]));


But instead of where i have written lsb7 it would be
Code: Select all
data[8] = (0x7F) - (0b01111111 & (data[0] + data[1] + data[2] + data[3] + data[4] + data[5] + data[6] + data[7]))  ;

?

Which compiles but gives the wrong result, in the code i emailed to you it should return '191' if joystick is in neutral (or if i hard code the values in the // notes)

Incidentally in the startup packet...
Code: Select all
data[9] = (0x7F) - (data[0] + data[1] + data[2] + data[3] + data[4] + data[5] + data[6] + data[7] + data[8]);

returns the expected '141'

I am able to see the output with the Logic Analyzer....am i missing some ()'s ?

i tried
Code: Select all
 data[8] = (0x7F) - ((0b01111111) & (data[0] + data[1] + data[2] + data[3] + data[4] + data[5] + data[6] + data[7]))  ;

but got a '=' instead of a '191'

Should i be doing a << shift to 'shuffle out' the bits i want to ignore ?

Binary math is a bit confusing at present.
http://greenmobility.com.au/rc-wheelchair-controller/
My YouTube Ch -- https://www.youtube.com/user/gcebiker
User avatar
gcebiker
 
Posts: 879
Joined: 11 Jul 2015, 14:20
Location: Gold Coast, Queensland, Australia.

Re: Arduino controlled wheelchair

Postby Irving » 14 Feb 2016, 19:38

what are data[x] declared as? byte or int? it shouldn't matter as we're only interested in the final byte so any overflow can be ignored tho that's not great programming practice.

141 is 0x8D - If this is expected then the final result cannot be generated from 0x7F - (0x7f & sum of bytes) as you have written since that will always generate a value between 0x00 and 0x7f

you need to apply the bitwise AND to each data byte but not to the final sum. If, as Lenny suggested, unused bytes in the packet are preset to 0 then try this:

Code: Select all
byte sum = 0;
for(int i=0; i < 9; i++)
      sum+=data[i] & 0x7f;  // 0x7f is same as 0b01111111 but easier to write/check
data[9] = 0x7f - sum;


else try
Code: Select all
int len = (int)(data[0] >>4) & 0x07); //assumes start byte is data[0]
byte sum = 0;
for(int i=0; i < len; i++)
      sum+=data[i] & 0x7f;  // 0x7f is same as 0b01111111 but easier to write/check
data[9] = 0x7f - sum;


what are the values for data[0] through [8] that should give 141 as the checksum?
C5/6 A (complete)
Puma 40, 75Ah LiFePO4 (pic is on tour @ Whistler, BC)
Puma 40 backup, 73Ah MK (for now)
Spectra Plus (weedy 40Ah MK)
User avatar
Irving
 
Posts: 2114
Joined: 04 Dec 2012, 11:51
Location: NW London

Re: Arduino controlled wheelchair

Postby LROBBINS » 14 Feb 2016, 21:50

My head is spinning too. Yesterday I just did some manual arithmetic and managed to get myself confused, so today, especially after your last post, I wrote a little Arduino program:
Code: Select all
byte data[10];

void setup() {
  Serial.begin(115200);
  Serial.println(__FILE__ " - " __DATE__ " " __TIME__);
  Serial.println();
  data[0] = (0x74);   // start identifier. " t "
  data[1] = (130);      // Joystick speed
  data[2] = (133);      // Joystick direction
  data[3] = (130);      // Max speed setting via turtle/hare buttons on joystick?
  data[4] = (128);      // Speed Fine Tune ?
  data[5] = (136);      // default horn off, horn on value is 130
  data[6] = (205);      //data[6] = 205;      // joystick On Value ?
  data[7] = (160);      //data[7] = 160;      // chair mode/ drive 128, tilt/aux output 129
  data[8] = (128);      //data[8] = 128;      //not used?
  CheckSum ();
}

void loop() {
}

void CheckSum (){
  byte ByteSum = (data[0] + data[1] + data[2] + data[3] + data[4] + data[5] + data[6] + data[7] + data[8]);
  int IntSum = (data[0] + data[1] + data[2] + data[3] + data[4] + data[5] + data[6] + data[7] + data[8]);
  Serial.print ("ByteSum = 0b");
  Serial.print (ByteSum, BIN);
  Serial.print (" = 0x");
  Serial.print (ByteSum, HEX);
  Serial.print (" = 0d");
  Serial.println (ByteSum);
  data[9] = 0x7F - ByteSum;
  Serial.print ("'byte' CheckSum = 0x7F - ByteSum = 0b");
  Serial.print (data[9], BIN);
  Serial.print (" = 0x");
  Serial.print (data[9], HEX);
  Serial.print (" = 0d");
  Serial.println (data[9]);
  Serial.println ();
  ByteSum = 0b01111111 & ByteSum,
  Serial.print ("7lsb ByteSum = 0b");
  Serial.print (ByteSum, BIN);
  Serial.print (" = 0x");
  Serial.print (ByteSum, HEX);
  Serial.print (" = 0d");
  Serial.println (ByteSum);
  data[9] = 0x7F - ByteSum;
  Serial.print ("'7lsb byte' CheckSum = 0x7F - 7lsb ByteSum =0b");
  Serial.print (data[9], BIN);
  Serial.print (" = 0x");
  Serial.print (data[9], HEX);
  Serial.print (" = 0d");
  Serial.println (data[9]);
  Serial.println ();
  Serial.println ("***********************************");
  Serial.println ();
  Serial.print ("IntSum = 0b");
  Serial.print (IntSum, BIN);
  Serial.print (" = 0x");
  Serial.print (IntSum, HEX);
  Serial.print (" = 0d");
  Serial.println (IntSum);
  data[9] = 0x7F - IntSum;
  Serial.print ("'byte' CheckSum = 0x7F - IntSum = 0b");
  Serial.print (data[9], BIN);
  Serial.print (" = 0x");
  Serial.print (data[9], HEX);
  Serial.print (" = 0d");
  Serial.println (data[9]);
  Serial.println ();
  IntSum = 0b01111111 & IntSum,
  Serial.print ("7lsb IntSum = 0b");
  Serial.print (IntSum, BIN);
  Serial.print (" = 0x");
  Serial.print (IntSum, HEX);
  Serial.print (" = 0d");
  Serial.println (IntSum);
  data[9] = 0x7F - IntSum;
  Serial.print ("'7lsb int' CheckSum = 0x7F - 7lsb IntSum =0b");
  Serial.print (data[9], BIN);
  Serial.print (" = 0x");
  Serial.print (data[9], HEX);
  Serial.print (" = 0d");
  Serial.println (data[9]);
  Serial.println ();
  Serial.println ("***********************************");
  Serial.println ();
} //end CheckSum ()

I first just summed Data[0] through Data[8] into a byte variable. Doing this, the sum will roll over every time it exceeds 254. The result is :
Code: Select all
ByteSum = 0b11110010 = 0xF2 = 0d242

I then subtracted this from 0x7F and got:
Code: Select all
'byte' CheckSum = 0x7F - ByteSum = 0b10001101 = 0x8D = 0d141
This now matches the "141" you say you expect for the checksum (not the "161" you said in an earlier post).

Next, I took the 7 lsb of the sum of Data[0] through Data[8] and subtracted that from 0x7F. This is what the Shark spec says the checksum should be, but results are:
Code: Select all
7lsb ByteSum = 0b1110010 = 0x72 = 0d114
'7lsb byte' CheckSum = 0x7F - 7lsb ByteSum =0b1101 = 0xD = 0d13
This certainly does not match your expected value of "141".

Then I did the same sort of thing, but put the sum into an integer variable. Even though there is now no rollover, the end result is actually the same. The integer sum of the bytes is 0d1266, but when this is subtracted from 0x7F and cast into a byte (Data[9]) it again gives "141", but if I just use the 7 lsb of the sum, the end result is again NOT "141":
Code: Select all
IntSum = 0b10011110010 = 0x4F2 = 0d1266
'byte' CheckSum = 0x7F - IntSum = 0b10001101 = 0x8D = 0d141

7lsb IntSum = 0b1110010 = 0x72 = 0d114
'7lsb int' CheckSum = 0x7F - 7lsb IntSum =0b1101 = 0xD = 0d13


BTW, this actually matches what I got just doing the arithmetic by hand; I was confused yesterday because I got either "141" or "13" and never got the "161" you originally said was the expected checksum.

I haven't gone through everything you had in your last post, but did notice a couple things. For one, sometimes you are summing data[0] through data[8] and in other examples you've summed only data[0] through data[7] which will certainly give a different result. Then at some point you got an output of "=" instead of a number, which means that somewhere the calculated byte was printing as an ASCII character (presumably the one corresponding to whatever number you'd calculated: = is ASCII 61). Byte and char are both 8 bit unsigned variables in Arduino-flavor C, so really the same. What you print out depends on how you write the print statement. Declaring a variable as byte or char is mostly just a mnemonic device for when you need to re-read some code you've written; it reminds you whether you intend to use it as a number or as a character.

In any case, it looks like that 7 least significant bits business in the Shark document is misleading or just plain wrong, and that you were on the right track with your first attempt. You just have to be careful in your typing - "141" vs "161" or putting in 0xFF instead of 0x7F, or sometimes not summing all of the bytes. You can just sum data[0] through data[8] and then subtract that from 0x7F. BUT, to make clear what is happening either use parentheses to group the sum part,
Code: Select all
data[9] = 0x7F - (data[0]+data[1]+data[2]+data[3]+data[4]+data[5]+data[6]+data[6]+data[8]);
or just do it in two steps; first add them up then subtract from 0x7F.
Code: Select all
data[9] = data[0]+data[1]+data[2]+data[3]+data[4]+data[5]+data[6]+data[6]+data[8];
data[9] = 0x7F - data[9];
Do make sure to always reset all of Data[i] to 0 before receiving a message so that a short one, with few bytes of data, will not have old data when you make the sum. (I am assuming that you will eventually want to receive as well as send messages.)

Ciao,
Lenny
LROBBINS
 
Posts: 5789
Joined: 27 Aug 2010, 09:36
Location: Siena, Italy

Re: Arduino controlled wheelchair

Postby gcebiker » 15 Feb 2016, 02:07

LROBBINS wrote:I haven't gone through everything you had in your last post, but did notice a couple things. For one, sometimes you are summing data[0] through data[8] and in other examples you've summed only data[0] through data[7] which will certainly give a different result.


First 't' packet is the joystick "specs" date of manufacture and all that....my notes are not up to date for that first packet. But the first packet is a straight write of values (as apposed to unsigned/signed/unit8 numbers)

Second packet is data from joystick, actual values.
when i sharkSerial.write
data[1] = 192;
data[2]= 191;
I get a response from the base.

when changed to sharkSerial.write
data[1] = (yPotValMapped); // Joystick Y value
data[2] = (xPotValMapped); // Joystick X value

it works (as i messed with the mapping till it gave the 192/191 values) until i move the joystick.

At this point i remembered the document talking about a checksum, :!: I thought, i am writing a fixed check sum instead of calculating it.

i have declared the variables as "int" Irvings questions made me remember that (...i think) the "int" is a 16bit storage space and if i called that later on in some math it would skew the results.

I will change the "int" to "unsigned char" and see what happens, certainly its the biggest difference (in terms of bit math?)between the " t " packet and the " ' " packet.

I am working on tidying up the code notes, i kept the old ones as i was working backwards and forwards from a version and needed the old notes to remember what i had done/changed.
http://greenmobility.com.au/rc-wheelchair-controller/
My YouTube Ch -- https://www.youtube.com/user/gcebiker
User avatar
gcebiker
 
Posts: 879
Joined: 11 Jul 2015, 14:20
Location: Gold Coast, Queensland, Australia.

Re: Arduino controlled wheelchair

Postby gcebiker » 15 Feb 2016, 02:21

I dont use the terminal window to see the results.(so avoiding the print / serial write, and some versions of my code use the uart ...till i fried my spare DG419, 10 more on order from element 14)

I've a Saleae Logic4, the screen shots are i have posted are from it, i was getting myself confused with the serial monitor, the Logic analyzer is heaps easier to read...being that i can see the timing as well.

At this point i am not interested in reading what the base is saying.

I am only interested in getting the BIT MATH right for the checksum.
http://greenmobility.com.au/rc-wheelchair-controller/
My YouTube Ch -- https://www.youtube.com/user/gcebiker
User avatar
gcebiker
 
Posts: 879
Joined: 11 Jul 2015, 14:20
Location: Gold Coast, Queensland, Australia.

Re: Arduino controlled wheelchair

Postby gcebiker » 15 Feb 2016, 02:27

A copy of the code i have emailed so some of you, with notes removed/added.
Code: Select all





// This sketch is to emulate the packet of data that the Shark Joystick sends
/******************************************************************************
      Author: Tony Matthews ammatthews at gmail dot com
      License: FreeBSD
    ******************************************************************************/
/******************************************************************************
  Copyright (c) 2015, Tony Matthews
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

  The views and conclusions contained in the software and documentation are those
  of the authors and should not be interpreted as representing official policies,
  either expressed or implied, of the FreeBSD Project.

*******************************************************************************/

// This code is incomplete and still under revision.
// Its also got junk that may not be needed,
// Early testing phases.



// Names for Pins and what they are connected to
// getting ready to use GCDuiNode with the RF24 or Wii Nunchuck (currently hard wired)



// Pin outs for RS485 chip
const int onOffPin = 3;      // Digital Pin for software on/off button
const int roPin = 11;         // to RO of Max485
const int rePin = 10;         // to RE of Max485
const int dePin = 9;         // to DE of Max485
const int diPin = 8;         // to DI of Max485

const int dataSwitch = 6;   //  Digital Switch for DG419

const int led = 13 ;    // LED state indicator pin

//Boolean name holder for current state.
boolean onOffstate = LOW;

// Analog input pins assignments
const int yPot = A0;    // Y Pot input value
const int xPot = A1;    // X Pot input value

// Names for analogRead values of Analog Pots
int yPotVal;
int xPotVal;

// Names for Mapped analogRead Values of Pots
unsigned char yPotValMapped;
unsigned char xPotValMapped;


// Size of data packet, tho the packets are not constrained to this size.
// May need to change this value.
unsigned char data[12];
unsigned long timer = 0;

#include <SoftwareSerial.h>
SoftwareSerial sharkSerial (roPin, diPin, false);    // 'true' sets this to invert software serial output.





void setup()
{
  sharkSerial.begin(38400);
  pinMode(led, OUTPUT);        // Arduino led to monitor on or off state.
  pinMode(onOffPin, INPUT_PULLUP);  // Software on/off button, turn on internal pull up resistors.
  // Set Data switch pin to Output
  digitalWrite(dataSwitch, LOW);  //Start Data in LOW = PNP 'on' NPN 'Off'
}


void loop() {
  // Starts in Off state from physical power on.
  // Check state, if "on" , "turn off" and visa versa.
  if (digitalRead(onOffPin) == LOW && onOffstate == HIGH)
  {
    onOffstate = !onOffstate;    //toggles onOffstate from HIGH to LOW (if it was HIGH when the on/off button is pressed)
    digitalWrite(dePin, LOW);    // hold dePin low when 'off'
    digitalWrite(dataSwitch, LOW);
    digitalWrite(led, onOffstate);    // Turn off the LED on arduino as indication of state
    delay (300);       //debounce switch delay
  }

  // check state, if on/off button is pressed, change state to "ON" and run start up sequence.
  else if (digitalRead(onOffPin) == LOW && onOffstate == LOW)
  {
    onOffstate = !onOffstate;     // toggle state to HIGH if in'off mode' and on/off button is pressed
    digitalWrite(led, onOffstate); // turn on LED pin to get visual indication of on/off state
    digitalWrite(dePin, HIGH);    // Hold dePin high when transmitting.
    sharkStartup();              // call function sharkStartup()
  }


  if (onOffstate == HIGH)
  {
    digitalWrite(led, onOffstate);    //Keep arduino LED 'on' as indication of mode arduino is in
    digitalWrite(dePin, HIGH);       // Hold dePin high when transmitting.
    digitalWrite(dataSwitch, LOW);
    sharkOnMode();                   // Call sharkOnMode() to write joystick data to inverted serial bus
  }

}


void sharkStartup () {
  {
    pinMode(dataSwitch, OUTPUT);
    digitalWrite(dataSwitch, HIGH);    // Flip data switch, HIGH = PNP 'Off', NPN 'ON'
    delay(298);
    digitalWrite(dataSwitch, LOW);    // Flip dats switch, LOW = PNP 'On', NPN 'Off'
    delay(10);
  }

  {
    //build serial packet joystick manufacture info
    data[0] = (0x74);   // start identifier  " t "
    data[1] = (130);      //
    data[2] = (133);      //
    data[3] = (130);      //
    data[4] = (128);      //
    data[5] = (136);      //
    data[6] = (205);      //
    data[7] = (160);      //
    data[8] = (128);      //
    data[9] = (0x7F) - (data[0] + data[1] + data[2] + data[3] + data[4] + data[5] + data[6] + data[7] + data[8]); //Checksum  OK = (141);
    data[10] = (15);      // all packets end with this identifier



    for (unsigned char i = 0; i < 11; i++)
      sharkSerial.write(data[i]);

  }
  delay(16);
}


void sharkOnMode() {


  {
    yPotVal = analogRead(yPot);
    delay(2);
    xPotVal = analogRead(xPot);

    yPotValMapped = map(yPotVal, 0, 1023, 128, 255) + 1; // Map min/max pot values to match min/max original Shark joystick values.
    xPotValMapped = map(xPotVal, 0, 1023, 128, 255); // Map X values
  }
  {

    // " ' " build serial packet - this is the packet i need to get the bit math right for the checksum
    data[0] = (0x60);   // Joystik packets start with this
/*data [1] and [2] are the only variables , declared as 'unsigned char' at the top
 i have fixed values in the example below so i can work on the BIT Math with constants (because i did a data read)
 and know what the checksum should be '191'
*/   
    data[1] = 192;    //(yPotValMapped); // Joystick Y value 192 / neutral
    data[2] = 191;    //(xPotValMapped); // Joystick X value 191 / neutral
    data[3] = 255;      // Max speed setting via turtle/hare buttons on joystick
    data[4] = 214;      // Speed Fine Tune ?
    data[5] = 128;     // default horn off, horn on value is 130
    data[6] = 140;     // joystick On Value ?
    data[7] = 128;     // chair mode/ drive 128, tilt/aux output 129
    data[8] = (0x7F) - (data[0] + data[1] + data[2] + data[3] + data[4] + data[5] + data[6] + data[7])  ;     // checksum '191' if neutral
    data[9] = 15;       // all packets end with this identifier

    for (unsigned char i = 0; i < 10; i++)
      sharkSerial.write(data[i]);
  }
  delay(16);    //Delay next packet 17ms input from Shark joystick

}



http://greenmobility.com.au/rc-wheelchair-controller/
My YouTube Ch -- https://www.youtube.com/user/gcebiker
User avatar
gcebiker
 
Posts: 879
Joined: 11 Jul 2015, 14:20
Location: Gold Coast, Queensland, Australia.

Re: Arduino controlled wheelchair

Postby gcebiker » 15 Feb 2016, 04:27

in the manual it says that
A one byte checksum, which is defined as 0x7F - ( least-significant 7 bits of ( sum of all data bytes and start byte))


Shark remote power up is 11 bytes. (" t ", data bytes, checksum, transmit finished byte)
Shark data packets are 10 bytes.( " ' " ,data bytes, checksum, transmit finished byte)

if i just stick to the data packets (joystick position / speed / direction)
- with an integer i will name 'checksum'
checksum = (sum of all data bytes and start byte);
checksum = (data[0] + data[1] + data[2] + data[3] + data[4] + data[5] + data[6] + data[7]);
checksum = ((0x60) + 192 + 191 + 255 + 214 + 128 + 140 + 128);
checksum = (0b 0100 0000); // which equals dec,64 or hex, 0x40 (i used the LA to see the result of the math)
checksum = (0b 100 0000);// being the least significant 7 bits which is the same as the above line '64'
checksum = (0x7f) - (0x40);
checksum = (0x3f); // the expected result here is 191 (0xBF)

I am missing something, the logic analyzer has built in conversions for hex, dec, binary, global.
writting it out long hand has not helped as much as i hoped :cry:
http://greenmobility.com.au/rc-wheelchair-controller/
My YouTube Ch -- https://www.youtube.com/user/gcebiker
User avatar
gcebiker
 
Posts: 879
Joined: 11 Jul 2015, 14:20
Location: Gold Coast, Queensland, Australia.

Re: Arduino controlled wheelchair

Postby gcebiker » 15 Feb 2016, 07:28

Irving wrote:
Code: Select all
byte sum = 0;
for(int i=0; i < 9; i++)
      sum+=data[i] & 0x7f;  // 0x7f is same as 0b01111111 but easier to write/check
data[9] = 0x7f - sum;



Worked, plugged it in and worked right away....got expected 191

for Joystick Data packets.
Code: Select all
// " ' " build serial packet - this is the packet i need to get the bit math right for the checksum
    data[0] = (0x60);   // Joystik packets start with this
    /*data [1] and [2] are the only variables , declared as 'unsigned char' at the top
      i have fixed values in the example below so i can work on the BIT Math with constants (because i did a data read)
      and know what the checksum should be '191'
    */
    data[1] = 192;    //(yPotValMapped); // Joystick Y value 192 / neutral
    data[2] = 191;    //(xPotValMapped); // Joystick X value 191 / neutral
    data[3] = 255;      // Max speed setting via turtle/hare buttons on joystick
    data[4] = 214;      // Speed Fine Tune ?
    data[5] = 128;     // default horn off, horn on value is 130
    data[6] = 140;     // joystick On Value ?
    data[7] = 128;     // chair mode/ drive 128, tilt/aux output 129
    byte sum = 0;
    for (int i = 0; i < 8; i++)
      sum += data[i] & 0x7f; // 0x7f is same as 0b01111111 but easier to write/check
    data[8] = 0x7f - sum;
    data[9] = 15;       // all packets end with this identifier

    for (unsigned char i = 0; i < 10; i++)
      sharkSerial.write(data[i]);
  }


Ill try it on the chair later , when its night time and i can unplug and wire the chair to the pc...tried to do it during the day earlier in the week...phone rang and i just automatically tried to turn around and nothing worked...(also was out of gear), lucky my leggy wife was about and could get to the phone for me.

I remember reading about the BitMath sum+= but i had forgotten where and exactly what it meant, so much to hold in your head...
http://greenmobility.com.au/rc-wheelchair-controller/
My YouTube Ch -- https://www.youtube.com/user/gcebiker
User avatar
gcebiker
 
Posts: 879
Joined: 11 Jul 2015, 14:20
Location: Gold Coast, Queensland, Australia.

Re: Arduino controlled wheelchair

Postby gcebiker » 15 Feb 2016, 12:34

I had hopped to take a break and show you some shots of the chair responding to code changes...

Unfortunately, on both boards (soft and hardwired) i am getting loads of noise, its been happening on and off for weeks , ive not been able to pin down the cause.

Its got to be wiring related, possibly not having diodes on the DG419...but its not supposed to need them when powered at 15+ volts...idk

So instead here is a picture of what i am seeing....
Image
http://greenmobility.com.au/rc-wheelchair-controller/
My YouTube Ch -- https://www.youtube.com/user/gcebiker
User avatar
gcebiker
 
Posts: 879
Joined: 11 Jul 2015, 14:20
Location: Gold Coast, Queensland, Australia.

Re: Arduino controlled wheelchair

Postby gcebiker » 15 Feb 2016, 13:03

Thank you Irving, i don't understand it yet but i will, got the code working..on usb power at least, at 15v i have a hell of a lot of noise.
Irving wrote:
Code: Select all
byte sum = 0;
for(int i=0; i < 9; i++)
      sum+=data[i] & 0x7f;  // 0x7f is same as 0b01111111 but easier to write/check
data[9] = 0x7f - sum;




Copy of semi working code.
- Bugs, led is on very dimly when in 'off' mode, only seems to happen on the Freetronics board not the Nano V3.0
- Heaps and heaps of noise on High side of Async line, no idea what is causing it but will look to order some manufactured boards to rule out loose wiring in prototype boards.
Code: Select all

With help from
Lenny,
GizmoSmith,
Jim C,
and my very supportive wife, Naomi.



// This sketch is to emulate the packet of data that the Shark Joystick sends
/******************************************************************************
      Author: Tony Matthews ammatthews at gmail dot com
      License: FreeBSD
    ******************************************************************************/
/******************************************************************************
  Copyright (c) 2015, Tony Matthews
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

  The views and conclusions contained in the software and documentation are those
  of the authors and should not be interpreted as representing official policies,
  either expressed or implied, of the FreeBSD Project.

*******************************************************************************/

// This code is incomplete and still under revision.
// Its also got junk that may not be needed,
// Early testing phases.



// Names for Pins and what they are connected to
// getting ready to use GCDuiNode with the RF24 or Wii Nunchuck (currently hard wired)



// Pin outs for RS485 chip
const int onOffPin = 3;      // Digital Pin for software on/off button
const int roPin = 11;         // to RO of Max485
const int rePin = 10;         // to RE of Max485
const int dePin = 9;         // to DE of Max485
const int diPin = 8;         // to DI of Max485

const int dataSwitch = 6;   //  Digital Switch for DG419

const int led = 13 ;    // LED state indicator pin

//Boolean name holder for current state.
boolean onOffstate = LOW;

// Analog input pins assignments
const int yPot = A0;    // Y Pot input value
const int xPot = A1;    // X Pot input value

// Names for analogRead values of Analog Pots
int yPotVal;
int xPotVal;

// Names for Mapped analogRead Values of Pots
unsigned char yPotValMapped;
unsigned char xPotValMapped;


// Size of data packet, tho the packets are not constrained to this size.
// May need to change this value.
unsigned char data[12];
unsigned long timer = 0;

#include <SoftwareSerial.h>
SoftwareSerial sharkSerial (roPin, diPin, false);    // 'true' sets this to invert software serial output.





void setup()
{
  sharkSerial.begin(38400);
  pinMode(led, OUTPUT);             // Arduino led to monitor on or off state.
  digitalWrite(led, LOW);           // led staying on (very dimly) in off mode, not sure what thats all about
  pinMode(onOffPin, INPUT_PULLUP);  // Software on/off button, turn on internal pull up resistors.
  pinMode(dataSwitch, OUTPUT);      // Set Data switch pin to Output
  digitalWrite(dataSwitch, LOW);    //Start Data in LOW, Output still got heaps of noise, new chips coming to see if the old ones are the issue.
}


void loop() {
  // Starts in Off state from physical power on.
  // Check state, if "on" , "turn off"
  if (digitalRead(onOffPin) == LOW && onOffstate == HIGH)
  {
    onOffstate = !onOffstate;    //toggles onOffstate from HIGH to LOW (if it was HIGH when the on/off button is pressed)
    digitalWrite(dePin, LOW);    // hold dePin low when 'off'
    digitalWrite(dataSwitch, LOW);
   
    digitalWrite(led, onOffstate);    // Turn off the LED on arduino as indication of state
    delay (300);       //debounce switch delay
  }

  // check state, if on/off button is pressed, change state to "ON" and run start up sequence.
  else if (digitalRead(onOffPin) == LOW && onOffstate == LOW)
  {
    onOffstate = !onOffstate;     // toggle state to HIGH if in'off mode' and on/off button is pressed
    digitalWrite(led, onOffstate); // turn on LED pin to get visual indication of on/off state
    digitalWrite(dePin, HIGH);    // Hold dePin high when transmitting.
    sharkStartup();              // call function sharkStartup()
  }


  if (onOffstate == HIGH)
  {
    digitalWrite(led, onOffstate);    //Keep arduino LED 'on' as indication of mode arduino is in
    digitalWrite(dePin, HIGH);       // Hold dePin high when transmitting.
    digitalWrite(dataSwitch, LOW);
    sharkOnMode();                   // Call sharkOnMode() to write joystick data to inverted serial bus
  }

}


void sharkStartup () {
  {
    pinMode(dataSwitch, OUTPUT);
    digitalWrite(dataSwitch, HIGH);    // Flip data switch, HIGH = PNP 'Off', NPN 'ON'
    delay(298);
    digitalWrite(dataSwitch, LOW);    // Flip dats switch, LOW = PNP 'On', NPN 'Off'
    delay(10);
  }

  {
    //build serial packet joystick manufacture info
    data[0] = (0x74);   // start identifier  " t "
    data[1] = (130);      //
    data[2] = (133);      //
    data[3] = (130);      //
    data[4] = (128);      //
    data[5] = (136);      //
    data[6] = (205);      //
    data[7] = (160);      //
    data[8] = (128);      //
    byte sum = 0;
    for (int i = 0; i < 9; i++)
      sum += data[i] & 0x7f;    // 0x7f is same a ;s 0b01111111 but easier to write/check
    data[9] = 0x7f - sum;       //Checksum  OK = (141)
    data[10] = (15);      // all packets end with this identifier



    for (unsigned char i = 0; i < 11; i++)
      sharkSerial.write(data[i]);

  }
  delay(16);
}


void sharkOnMode() {


  {
    yPotVal = analogRead(yPot);
    delay(2);
    xPotVal = analogRead(xPot);

    yPotValMapped = map(yPotVal, 0, 1023, 128, 255) + 1; // Map min/max pot values to match min/max original Shark joystick values.
    xPotValMapped = map(xPotVal, 0, 1023, 128, 255); // Map X values
  }
  {

    // " ' " build serial packet - this is the packet i need to get the bit math right for the checksum
    data[0] = (0x60);   // Joystik packets start with this
    data[1] = (yPotValMapped); // Joystick Y value 192 / neutral
    data[2] = (xPotValMapped); // Joystick X value 191 / neutral
    data[3] = 255;      // Max speed setting via turtle/hare buttons on joystick
    data[4] = 214;      // Speed Fine Tune ?
    data[5] = 128;     // default horn off, horn on value is 130
    data[6] = 140;     // joystick On Value ?
    data[7] = 128;     // chair mode/ drive 128, tilt/aux output 129
    byte sum = 0;
    for (int i = 0; i < 8; i++)
      sum += data[i] & 0x7f; // 0x7f is same as 0b01111111 but easier to write/check
    data[8] = 0x7f - sum;     // if neutral joystick should read 191
    data[9] = 15;       // all packets end with this identifier

    for (unsigned char i = 0; i < 10; i++)
      sharkSerial.write(data[i]);
  }
  delay(16);    //Delay next packet 17ms input from Shark joystick

}



http://greenmobility.com.au/rc-wheelchair-controller/
My YouTube Ch -- https://www.youtube.com/user/gcebiker
User avatar
gcebiker
 
Posts: 879
Joined: 11 Jul 2015, 14:20
Location: Gold Coast, Queensland, Australia.

Re: Arduino controlled wheelchair

Postby gcebiker » 15 Feb 2016, 15:08

Still dont know what is causing the noise on data lines, but got a clean capture, checksum now working thanks to Irving, not far away now. Chair still not moving but i guess because i am sending the packets from the first microsecond of the Original SR....now to track down packets from when it actually kicks in and starts moving the chair.

Fun times...but have to work, Sailability Tuesdays, chiller repairs Wednesday, Aquaponics upgrades Thursday,
Wife Leaving me on Friday...for 10days on holiday :P

So much stuff coming in the next week on order.
- Digi Spark Pro's + shields http://digistump.com/products/109
- 50 Dip 8 sockets , ebay
- 50 Max485 chips...thanks to a misread on the ebay listing.
- 10 DG419's from Element14
more protype boards then moving onto ordering boards online.
...i cant wait to actually be able to use the tilt actuator built into this chair i have not been able to move for years...

The money shot...Thank you all.
Image
http://greenmobility.com.au/rc-wheelchair-controller/
My YouTube Ch -- https://www.youtube.com/user/gcebiker
User avatar
gcebiker
 
Posts: 879
Joined: 11 Jul 2015, 14:20
Location: Gold Coast, Queensland, Australia.

Re: Arduino controlled wheelchair

Postby ex-Gooserider » 16 Feb 2016, 05:49

Have you tried adding any filter caps between the data lines and ground to get rid of the noise? Also sprinkle liberally with the 'magic fairy dust' of digital electronics - a 0.1uF cap across the power supply pins of every chip.... I have also seen a strong suggestion that it helps with noise suppression to tie any unused input pins to one of the rails, rather than letting them float... The explanation was that a floating pin could introduce noise by crosstalk since it was in an 'undefined' state...

ex-Gooserider

gcebiker wrote:Still dont know what is causing the noise on data lines, but got a clean capture, checksum now working thanks to Irving, not far away now. Chair still not moving but i guess because i am sending the packets from the first microsecond of the Original SR....now to track down packets from when it actually kicks in and starts moving the chair.

Fun times...but have to work, Sailability Tuesdays, chiller repairs Wednesday, Aquaponics upgrades Thursday,
Wife Leaving me on Friday...for 10days on holiday :P

So much stuff coming in the next week on order.
- Digi Spark Pro's + shields http://digistump.com/products/109
- 50 Dip 8 sockets , ebay
- 50 Max485 chips...thanks to a misread on the ebay listing.
- 10 DG419's from Element14
more protype boards then moving onto ordering boards online.
...i cant wait to actually be able to use the tilt actuator built into this chair i have not been able to move for years...

The money shot...Thank you all.
Image
T-5, ASIA-B
Jazzy 1100
Jazzy Select 6
Quickie Q-7
Invacare Mariner
Want to make / get a better chair, ideally one that stands.
User avatar
ex-Gooserider
 
Posts: 6228
Joined: 15 Feb 2011, 06:17
Location: Billerica, MA. USA

Re: Arduino controlled wheelchair

Postby gcebiker » 16 Feb 2016, 11:03

I'm farily certain its the DG419 cmos switch causing all the trouble, the spec sheet indicates
If power-supply sequencing is not possible,
add two small, external signal diodes in series with
the supply pins for overvoltage protection (Figure 1).


Ive the diodes and will add them to see if it makes a difference.
http://greenmobility.com.au/rc-wheelchair-controller/
My YouTube Ch -- https://www.youtube.com/user/gcebiker
User avatar
gcebiker
 
Posts: 879
Joined: 11 Jul 2015, 14:20
Location: Gold Coast, Queensland, Australia.

Re: Arduino controlled wheelchair

Postby LROBBINS » 16 Feb 2016, 23:27

I'm about to throw a wrench into the works.

The definition of the checksum given in the Shark documentation is:
Finally all packets except for the Transmit Finished packet shall include a one-byte checksum, which is defined as 0x7F - ( least-significant 7 bits of ( sum of all data bytes and start byte ) ).

Doing the calculation in accord with the parentheses in the definition that is:
(1) find the sum of the data bytes and start byte
(2) take the 7 lsb of that sum
and
(3) subtract that number from 0x7F

The result however, for the sample packet, is not the expected 141, but 13 (whether the sum is done as a byte with rollover, or as an integer truncated to 7 lsb)

We now have three procedures that did give 141:
(1) just sum as a byte and subtract from 0x7F
(2) just sum as an integer, truncate to a byte, and subtract from 0x7F
or
(3) find the 7 lsb of each byte, sum those and subtract from 0x7F

These give 141, but none of them are doing the calculation the way the document says it should be done! However, we have lost sight of something else that's in the documentation on p. 2):
While the data format is 8 bits, bit 7 in each byte shall be used to indicate the first byte of a packet. Bit 7 shall be CLEAR (0) for
the first byte in a packet, and SET (1) for all other bytes. If there is a slight timing difference between the sending and receiving
modules, such that the receiver is slightly faster than the sender, having bit 7 set in the majority of the data bytes will give the
greatest chance of correct reception.
This means that each transmitted byte carries 7 bits of actual information.


So the checksum is NOT really 141, it is a 7-bit number and then bit 7 gets set to 1 (just as it is for bytes 1 through 8; it's set to 0 for byte 0). Hence, the calculated checksum should be the 7 lsb of 141 which is GUESS WHAT - 13.

In other words, it seems that we should calculate the checksum exactly the way it's defined (i.e. a value of 13), then before putting it into a packet to be transmitted we set bit 7 to 1 changing the 13 to 141 (we do 13 & 0xFF). If the check sum (calculated as per the documentation) turned out to be 137 or more, bit 7 is already 1, and it stay that way and would get transmitted unchanged.

You need to take this into account when you "sniff" other messages - the data is only 7 bits long. To create a new packet to transmit, you take the data for the start byte and do & 0x7F, and for all the other bytes you do & 0xFF, filling the msb with the "padding" needed to identify "start of packet" and waste one bit's worth of time between each piece of data.

Ciao,
Lenny
LROBBINS
 
Posts: 5789
Joined: 27 Aug 2010, 09:36
Location: Siena, Italy

Re: Arduino controlled wheelchair

Postby gcebiker » 17 Feb 2016, 00:04

This is it sampled with two stop bits, with 7 bits i get errors on the Logic4

This is ONLY the start packet which is longer than the joydata packets.
Image
http://greenmobility.com.au/rc-wheelchair-controller/
My YouTube Ch -- https://www.youtube.com/user/gcebiker
User avatar
gcebiker
 
Posts: 879
Joined: 11 Jul 2015, 14:20
Location: Gold Coast, Queensland, Australia.

Re: Arduino controlled wheelchair

Postby LROBBINS » 17 Feb 2016, 01:59

Each byte that is transmitted IS 8 bits, but those 8 bits are made up of 7 bits of data and 1 bit added to either identify the first byte, in which case the added bit is a 0, or to take up time between data items, in which case it's a 1. For example, if some variable, perhaps joystick throw, can take values from 0 to 100 (0b0 to 0b0110100). The transmitter adds a 1 in the bit7 position (by doing | 0x80) and the byte in the packet that's transmitted will go from 128 to 228 (0b10000000 to 0b1110100). If receiver sees, as one example, 137 (0b10001001), it does & 0xFF to remove that "spacer" bit, and knows that the variable's value is 9 (0b1001).
LROBBINS
 
Posts: 5789
Joined: 27 Aug 2010, 09:36
Location: Siena, Italy

Re: Arduino controlled wheelchair

Postby gcebiker » 17 Feb 2016, 02:39

Ill be adding the right value terminating resistor today, i only have a 10k in there for now.

/edit...:arrow: bought the wrong resistors, 120k's.... Ill go get some 22k's after i finish work today i guess.
http://greenmobility.com.au/rc-wheelchair-controller/
My YouTube Ch -- https://www.youtube.com/user/gcebiker
User avatar
gcebiker
 
Posts: 879
Joined: 11 Jul 2015, 14:20
Location: Gold Coast, Queensland, Australia.

Re: Arduino controlled wheelchair

Postby LROBBINS » 17 Feb 2016, 16:09

I've attached a zip file with a small Arduino sketch and a txt file of its output to illustrate using the definition of the data packet structure:
While the data format is 8 bits, bit 7 in each byte shall be used to indicate the first byte of a packet. Bit 7 shall be CLEAR (0) for
the first byte in a packet, and SET (1) for all other bytes. If there is a slight timing difference between the sending and receiving
modules, such that the receiver is slightly faster than the sender, having bit 7 set in the majority of the data bytes will give the
greatest chance of correct reception.
This means that each transmitted byte carries 7 bits of actual information.

along with the definition of the checksum:
Finally all packets except for the Transmit Finished packet shall include a one-byte checksum, which is defined as 0x7F - ( least-significant 7 bits of ( sum of all data bytes and start byte ) ).

to calculate the number to put into the checksum byte of a packet.

There are five different packets here, all with one start byte and 8 data bytes. The first one is the example you've been using, the others are just arbitrary packets with no particular meaning. Do note that the second packet is actually NOT a valid packet: the start byte should have bit7 set to 0, but in packet2 it is 128 which has bit7 = 1.

For each packet I calculated the sum in three different ways:
(1) just summing into a byte variable and letting it rollover naturally every time the intermediate sum is > 254
(2) summing into an integer variable, so there's no rollover. It will just be truncated to byte length later on.
(3) first removing the msb (bit7) from each byte and then summing as in 1
All three of these give different numbers, but that makes no difference after the next step.

Then I found the checksum using
Code: Select all
0x7F-(sum & 0x7F)
just as the document says we should. This gives us a 7 bit long datum, that we then need to convert to the byte to put in the packet.

To get the byte to put in our packet, I changed bit7 of that number to a 1 by doing (CkSum | 0x80).

So, for each of the 5 packets, there are 3 ways of calculating the sum, and for each sum there are 3 lines of output: the sum, the checksum, and the byte derived from that checksum; all of these are shown as binary, hex and decimal numbers.

This is the way the documentation says that the checksum is calculated and the way that the bytes in a packet are constructed (7 data bits + 1 bit set to 0, for the first byte, or 1, for all other bytes). It gives the right value for your example packet, and consistent results for the others I've tried. If you are having trouble following this logic, I suggest printing out the sketch and results files and going through them line by lines side by side.

Ciao,
Lenny

P.S. I doubt that lack of over voltage protection diodes or the wrong termination resistor value accounts for the noise. Much more likely, as Goose suggested, is noise on your power leads. You should have a large, low ESR capacitor (say 10 mfd) between the + and - power leads where the enter your breadboard and a 0.1 mfd connected between the Vss and Vdd pins of each chip mounted as close to those pins as possible. Also, if you still have things plugged into a breadboard, do be aware that those connections themselves are a source of noise. If you're having noise problems now, just imagine what it will be like when this is mounted on a chair with it's 24V brush motors.
Attachments
Shark checksum.zip
(1.86 KiB) Downloaded 298 times
LROBBINS
 
Posts: 5789
Joined: 27 Aug 2010, 09:36
Location: Siena, Italy

Re: Arduino controlled wheelchair

Postby gcebiker » 21 Feb 2016, 05:12

- Swapped out 'pin header' style DIP8 socket for 'Machined Gold pin' Dip8 socket.
(had a job earlier in the week where this was an issue so figured i may as well do it to my own as well)

- added 22k resistor to AB output of MAX485 board (now seeing Low side signal on Logic 4, was not visible before with 10k resistor)
- added signal diodes on DG419 chip +/- pins, data sheet calls for these to control correct boot up sequence within the chip.
- added 100nf filter cap on DG419 +/- per pretty much everyone's suggestion. :)

== for now the noise is gone, (i've always had a big cap on the power lines into the circuit, post 7812 reg chip)...lets hope thats sorted the noise issues out==

Picture...every one like boring trace pictures right ?
Image
http://greenmobility.com.au/rc-wheelchair-controller/
My YouTube Ch -- https://www.youtube.com/user/gcebiker
User avatar
gcebiker
 
Posts: 879
Joined: 11 Jul 2015, 14:20
Location: Gold Coast, Queensland, Australia.

Re: Arduino controlled wheelchair

Postby ex-Gooserider » 21 Feb 2016, 22:17

The 0.1uF cap across the power inputs, as close to the chip as possible is something that should be used on pretty much EVERY IC chip unless the data sheet explicitly says not to... Most chips draw a little bit of current when they switch, and that sudden surge can cause the voltage at the die to drop significantly - in some cases enough to go out of the specs for proper TTL logic... This also propagates back through the supply to neighbouring chips, as well as slightly altering the output wave form. It isn't quite as big of a problem with modern CMOS logic which isn't as power hungry, but was enough of an issue back in the early 7400 logic families that a lot of chip sockets even came with the caps built into the body of the socket...

However a lot of schematics either didn't show them, or hid them in a note off to one side as they added clutter to the drawing and 'everyone knew' enough to add them in even if they weren't shown...

ex-Gooserider
T-5, ASIA-B
Jazzy 1100
Jazzy Select 6
Quickie Q-7
Invacare Mariner
Want to make / get a better chair, ideally one that stands.
User avatar
ex-Gooserider
 
Posts: 6228
Joined: 15 Feb 2011, 06:17
Location: Billerica, MA. USA

PreviousNext

Return to Everything Powerchair

Who is online

Users browsing this forum: emilevirus, JMGarage, LROBBINS, ricardoh, yeshelp and 83 guests

 

  eXTReMe Tracker