I'm working on command-handler library and I have a big problem with F()
function.
Example sketch for library uses quite a lot of RAM, because it has to print a lot of text over UART. As before, I've used F()
to lower RAM usage. It worked on first!
Lib works with help of strtok
function. Command fomar is:
cmd1,..,paramN;..;cmdN,..,paramN
Commands are separated with ;
while command parameters(params) are separated with ,
Library works without any problems, it returns memory address(char*
) of any command and every param.
When I try to compare parameter/command with strcmp
it works only if all commands are in uppercase.
Let's take LED
command for example:
It works only with Led
, LED
or any case where is letter d in uppercase. led
won't work, and it will say that command le
doesn't exist. Yes, le
, it won't print led
. But, after DURATION
command, it somehow start working.
Memory for serial buffer is dynamicly allocaed in object constructor, in global scope.
Why? All those problems are because F()
. Can someone explain why? Here's the code and screenshot of serial monitor.
void execCmd(const char *set)
{
char *cmdParam = CMDHandler.find(set, CMD_PARAM);
if (!strcmp(cmdParam, "LED"))
{
// ONE WAY TO CHECK IF COMMAND HAS PARAM(S) - BEFORE GETTING PARAM(S) == BETTER WAY
if (!CMDHandler.count(CMDHandler.getNext(CMD_PARAM), CMD_PARAM))
{
Serial.print(F("->> Command LED: Current LED status is "));
Serial.println(digitalRead(LED_PIN));
return;
}
cmdParam = CMDHandler.find(nullptr, CMD_PARAM);
LEDStatus = 0;
uint8_t status = atoi(cmdParam);
digitalWrite(LED_PIN, status);
Serial.print(F("->> Command led: LED Status is "));
Serial.println(status, DEC);
}
else if (!strcmp(cmdParam, "LOOP"))
{
cmdParam = CMDHandler.find(nullptr, CMD_PARAM);
// SECOND WAY TO CHECK IF COMMAND HAS PARAM(S) - AFTER GETTING EVERY PARAM
if (cmdParam == nullptr)
{
Serial.println(F("->> Command LOOP: Expected one parameter!"));
return;
}
uint8_t status = atoi(cmdParam);
if (status)
{
LEDStatus = 2;
digitalWrite(LED_PIN, HIGH);
Serial.println(F("->> Command LOOP: LED Blink Loop is on!"));
delay(blinkDuration);
}
else
{
LEDStatus = 0;
digitalWrite(LED_PIN, LOW);
Serial.println(F("->> Command LOOP: LED Blink Loop is off!"));
}
}
else if (!strcmp(cmdParam, "DURATION"))
{
if (!CMDHandler.count(CMDHandler.getNext(CMD_PARAM), CMD_PARAM))
{
Serial.print(F("->> Command DURATION: Current blink duration is "));
Serial.print(blinkDuration, DEC);
Serial.println("ms");
return;
}
cmdParam = CMDHandler.find(nullptr, CMD_PARAM);
blinkDuration = atoi(cmdParam);
Serial.print(F("->> Command DURATION: New blink duration is "));
Serial.print(blinkDuration, DEC);
Serial.println("ms!");
}
else if (!strcmp(cmdParam, "HELP"))
{
Serial.println(F("------ HELP ------\n-> LED [0/1] - Turns off/on LED on pin 13\n-> LOOP [0/1] - Stops/starts blink loop with LED on pin 13\n-> DURATION [X] - Changes duration of LED loop blink. Recommended values is 50-500ms\n"));
}
else
{
Serial.print(F("->> Command "));
Serial.print(cmdParam);
Serial.println(F(" does not exist!"));
}
}
char *CMDHand::find(const char *input, uint8_t const type)
{
char *found = nullptr;
char separator = delimiter[type];
if (input != nullptr) // FIRST CALL
{
constrain[type] = input + strlen(input) - 1;
next[type] = input;
}
else if (next[type] > constrain[type]) return (nullptr);
found = strtok(next[type], &separator); // FOR SOME REASON IT DOES NOT WORK IF I PUT &delimiter[type] INSTEAD OF &separator
last[type] = next[type];
next[type] += strlen(found) + 1;
return (found);
}