Annotated Example Question

Could someone please explain why in:

Http://docs.spark.io/#/examples/control-leds-over-the-net

the API request would be =l1,HIGH

Based on the example shouldn’t it be =led1,HIGH

I can’t tell if this is a mistake or if I am missing something.

Hi @the_buff,

Sure thing! When you call that function, the parameters “l1,HIGH” are passed directly to that function in the string variable “command”;

index:   0123456789
command: l1,HIGH

In this case the “l” in “l1” is ignored entirely, and instead the character “1”, at index 1 is parsed using some ASCII math.

int pinNumber = command.charAt(1) - '0';
int pinNumber = (int)'1' - (int)'0' = 1
int pinNumber = 49 - 48 = 1

For reference here’s the code for the “ledControl” function from that example:

int ledControl(String command)
{
   int state = 0;
   //find out the pin number and convert the ascii to integer
   int pinNumber = command.charAt(1) - '0';
   //Sanity check to see if the pin numbers are within limits
   if (pinNumber < 0 || pinNumber > 1) return -1;

   // find out the state of the led
   if(command.substring(3,7) == "HIGH") state = 1;
   else if(command.substring(3,6) == "LOW") state = 0;
   else return -1;

   // write to the appropriate pin
   digitalWrite(pinNumber, state);
   return 1;
}

Hope that helps! :slight_smile:

Thanks,
David

1 Like

Because the ‘l’ (el) is ignored completely, and ‘l’ (el) is a bad character to use in general because it looks like a I (eye) or a 1 (one), it would be better to use ‘D’ in my opinion… at least then you have a better frame of reference to which pin is being toggled.

What about:

int pinNumber = command.charAt(1).toInt();  // convert single charater after the 'D' to an integer

if (pinNumber > 1) return -1; // allows 0 and 1

This example might be more intuitive for everyone. Also no way a single character (8-bit) can be a negative int (32-bit) number :wink:

1 Like

Ah, totally, I agree that would be more clear.

Thanks!
David

Just changing “ascii” to “character” makes it much easier for me to understand. Thank you.

This makes a little more sense. I’m assuming, for reasons I don’t fully understand yet, that the conversion to integer is necessary in this example?

Effectively since you’re doing math on single characters, their integer values are used. In this case they’re “ascii” encoded characters, so it’s the values from the ASCII character table. You can explicitly add the conversion, but the compiler will figure it out in this case. :smile:

Thanks,
David

This might help more…

ASCII        HEX     INTEGER
CHARACTER    VALUE   VALUE
-------------------------------
'0'          30      48
'1'          31      49
'2'          32      50
'3'          33      51
'4'          34      52
'5'          35      53
'6'          36      54
'7'          37      55
'8'          38      56
'9'          39      57

ASCII CHARACTER ‘7’ - ‘0’ is the same as saying INTEGER 55 - 48, which equals INTEGER 7.

2 Likes

Actually these integer values 30-39 are hex numbers 0x30-0x39 which is decimal 48-57, but the subtraction works out the same to e.g. 7 as above anyway :wink:

@the_buff, the reason why the character ‘1’ has to be converted to number 1 is that this number is the reference number for the pin - any other number e.g. 49 (= ‘1’) would map to another pin.

1 Like

Thanks! I usually double check my brain before posting something like that… I edited my post above.

Thanks for everyones' patience here.

Okay, so since the variable mapping that is done in the firmware:

int led1 = D0;

will not get passed through the Spark API (Particle Welcome to the Particle docs):

All Spark functions take a String as the only argument and must return a 32-bit integer.

The integer pin conversion is required. Correct?

Not quite.

It’s true, the function parameters are sent as string and thus any number needs to be converted from ASCII representation into its binary representation.

But the thing with the pin numbers is that pins are referenced via a set of numbers where D0 = 0, D1 = 1, D2 = 2, …, A0 = 10, A1 = 11, A2 = 12, …, RX = 18, TX=19, … (some Arduino/Wiring legacy - I guess)

In code you would use pre-defined compiler makros (e. g. #define TX 19) for these, since who would actually want to remember that you have to add 10 to the pin number when you mean an analog pin, or who rememberes 18/19 better than RX/TX (which is written on the board)?

But since you can’t use these compiler makros as Cloud API parameters, you have to find another way to pass in this number in a somehow understandable way, which led to the decision, to just define some kind of prefix (L for LED or D for Digital pin or A for Analog pin) plus the digit that you actually are interested in and then in code just drop all the blurb that’s only for the user to remember things better and just use the digit, translate it into the pin number you are looking for and there you go :wink:

I hope this makes things a bit clearer :partly_sunny:

1 Like

That does clear things up. Thank you.

Is there a place in the reference where I could have found this information myself?

I guess not - at leaset not concentrated in one place.

The question about char arithmetic was asked and answered on this forum one or two times before.
Once this is clear, the fact that D0 has the number 0 and D1 = 1 is implicitly “stated” in the code of a the annotated example you looked at.
That A pins have an offset of 10 is implicitly stated in the code of Tinker FW which is discussed in a forum thread or in the open source section under core-firmware/application.cpp.

So it’s quite scattered all over the place - but this is what the forum is intended for - to help new-commers to get up to speed faster, by taking advantage of the crowd knowledge base - since everyone had to start small :wink:

I found it enlightening to download the open source FW and browse through it - even though I didn’t intend to mess about with it originally.
But this gave me some ideas how to do things and now I feel I’d take on some FW tweaking tasks, too.

1 Like

These are some good suggestions! We are constantly improving our documentation, and just so you now, it’s all open source => you are more than welcome to edit the documentation and make a pull request!