Peristaltic Doser - Doser set amount over 24hr period

Yes, to all of the above.

Thank you! Now to figure out the retained variables.

Iā€™m getting an errorā€¦I need to declare the numberOfDoses in this group. I just donā€™t know how to declare it as I donā€™t know what atoi, atof, rmdr, and strtok do and how to do it.

int setupChannel(String cmd) { // cmd syntax: "channel#,startTime,doseRate, dose" (startTime is sent as hour*3600 + minute*60 + second)
    Serial.println(cmd);
    char *rmdr;
    char *stringArgs = (char*)cmd.c_str();
    int index = atoi(strtok_r(stringArgs, ",", &rmdr));
    Channel* c = &channels[index];
    c->onTime = atof(strtok_r(NULL, ",", &rmdr));
    c->doseRate = atof(strtok_r(NULL, ",", &rmdr));
    c->totalDose = atof(rmdr);
    float dosePerActuation = c->totalDose/numberOfDoses;
    float durationPerActuation = (dosePerActuation/c->doseRate) * 60; // assuming doseRate is in volume/minute
    c->offTime = c->onTime + durationPerActuation;

Are you sending the command string I suggested (how you change the code depends on where in the command string you have numberOfDoses)? I suggest that you Google atoi, strtok_r, etc. to understand what they mean and how to use them. You really shouldnā€™t be using code that you donā€™t understand. After doing that, you should attempt to fix the code yourself, and come back with a specific question if you canā€™t get it to work.

1 Like

Sounds good to me! I got the error on verification. Iā€™ll give it a shot though. Thank you.

So I read about atoi, atof and strtok_r. Of course the descriptions are not exactly in laymens termsā€¦I understand that atoi converts a string to an integer, seems pretty straight forward, but Iā€™m not sure I understand atof. Is it possible to give an easy to understand example?

Regarding strtok_r Iā€™m not 100% sure on this one yet either. I understand that it parses a string into a sequence of tokens, but Iā€™m not sure I understand whats going on in the brackets withinā€¦it looks like its referring to the string as a whole.

This stuff rattles my brain a bitā€¦I should probably look for a dummies version.

What's to understand? Those two methods are nearly identical; the only difference is that the "i" version converts a string to an integer, and the "f" version converts it to a float.

It only refers to the whole string the first time you call it, which is why you pass it the pointer to the string the first time. Each subsequent time you call it, you pass NULL instead, because the method keeps a pointer to the beginning of the next token. Look at the code in setupChannel -- each time you call the strtok_r you get the next piece of the string that's separated by what you pass as the second argument (a comma in our case). If you add one more piece to your command string, you just need to call it one more time.

Copy that...it didn't explain it that where I read it. Makes more sense now..thank you.

Regarding the command string, here is what I did...

int setupChannel(String cmd) { // cmd syntax: "channel#,startTime,doseRate, dose" (startTime is sent as hour*3600 + minute*60 + second)
    Serial.println(cmd);
    char *rmdr;
    char *stringArgs = (char*)cmd.c_str();
    int index = atoi(strtok_r(stringArgs, ",",",", &rmdr));
    Channel* c = &channels[index];
    c->onTime = atof(strtok_r(NULL, ",",",", &rmdr));
    c->doseRate = atof(strtok_r(NULL, ",",",", &rmdr));
    c->numberOfDoses = atoi(strtok_r(NULL, ",",",", &rmdr));
    c->totalDose = atoi(rmdr);
    float dosePerActuation = c->totalDose/numberOfDoses;
    float durationPerActuation = (dosePerActuation/c->doseRate) * 60; // assuming doseRate is in volume/minute
    c->offTime = c->onTime + durationPerActuation;

And this is the error I get:

multi-channel_doser_dupli.cpp: In function 'int setupChannel(String)':

  	multi-channel_doser_dupli.cpp:83:57: error: cannot convert 'const char*' to 'char**' for argument '3' to 'char* strtok_r(char*, const char*, char**)'
     c->calibrationEnd = 90000;
                                                     ^
  	multi-channel_doser_dupli.cpp:85:51: error: cannot convert 'const char*' to 'char**' for argument '3' to 'char* strtok_r(char*, const char*, char**)'
                                               ^
  	multi-channel_doser_dupli.cpp:86:53: error: cannot convert 'const char*' to 'char**' for argument '3' to 'char* strtok_r(char*, const char*, char**)'
                                                 ^
  	multi-channel_doser_dupli.cpp:87:58: error: cannot convert 'const char*' to 'char**' for argument '3' to 'char* strtok_r(char*, const char*, char**)'

You have an extra argument in your strtok_r functions. That function takes 3 arguments not 4. Remove one of the comma strings. Also, in the third to last line you have,

float dosePerActuation = c->totalDose/numberOfDoses;

There is no variable called numberOfDoses; that variable is part of the struct ao you need to use,

float dosePerActuation = c->totalDose/c->numberOfDoses;

Ok, made that correction -

int setupChannel(String cmd) { // cmd syntax: "channel#,startTime,doseRate, dose" (startTime is sent as hour*3600 + minute*60 + second)
    Serial.println(cmd);
    char *rmdr;
    char *stringArgs = (char*)cmd.c_str();
    int index = atoi(strtok_r(stringArgs, ",",", &rmdr));
    Channel* c = &channels[index];
    c->onTime = atof(strtok_r(NULL, ",",", &rmdr));
    c->doseRate = atof(strtok_r(NULL, ",",", &rmdr));
    c->numberOfDoses = atoi(strtok_r(NULL, ",",", &rmdr));
    c->totalDose = atoi(rmdr);
    float dosePerActuation = c->totalDose/c->numberOfDoses;
    float durationPerActuation = (dosePerActuation/c->doseRate) * 60; // assuming doseRate is in volume/minute
    c->offTime = c->onTime + durationPerActuation;

This error is the reason I had the extra set of " in the strtok_r statement.

multi-channel_doser_dupli.cpp:83:47: warning: missing terminating " character [enabled by default]
c->calibrationEnd = 90000;
^
multi-channel_doser_dupli.cpp:83:5: error: missing terminating " character
c->calibrationEnd = 90000;
^
multi-channel_doser_dupli.cpp:85:41: warning: missing terminating " character [enabled by default]
}
^
multi-channel_doser_dupli.cpp:85:5: error: missing terminating " character
}
^
multi-channel_doser_dupli.cpp:86:43: warning: missing terminating " character [enabled by default]
^
multi-channel_doser_dupli.cpp:86:5: error: missing terminating " character
^
multi-channel_doser_dupli.cpp:87:48: warning: missing terminating " character [enabled by default]
^
multi-channel_doser_dupli.cpp:87:5: error: missing terminating " character
^
multi-channel_doser_dupli.cpp: In function 'int setupChannel(String)':
multi-channel_doser_dupli.cpp:84:12: error: expected primary-expression before '*' token
}
^
multi-channel_doser_dupli.cpp:84:14: error: 'c' was not declared in this scope
}
^
make[1]: *** [../build/target/user/platform-6multi-channel_doser_dupli.o] Error 1
make: *** [user] Error 2
Error: Could not compile. Please review your code.

You now have 3 quotation marks, which is never correct; they always should be in pairs, and you only need one pair.

int index = atoi(strtok_r(stringArgs, ",", &rmdr));
// etc.

Ok so I added ā€™ c->numberOfDoses = atoi(strtok_r(NULL, ā€œ,ā€, &rmdr));ā€™

Iā€™m obviously reading whatā€™s in the parenthesis wrong then. I thought NULL referred to the channel argument, then onTime, doseRate followed by totalDose and each was separated by a comma. So my thought was since there will be one more argument in the string, that another comma was needed.

If Iā€™m completely wrong, just give me a pointer in the direction I need to look.

Thank you!

Whatā€™s in the parentheses, i.e. the arguments to the function, have nothing to do with how many pieces are in your string. There are only 3 arguments; the first one is either a pointer to your whole string (stringArgs) used only on the first call, or NULL on every call to the function after the first one. The second argument is your separator (","), and the third is for the remainder (always &rmdr in our code). So, NULL doesnā€™t really refer to anything ā€“ after the first call to the function, the function keeps a pointer to the beginning of the next piece of the string, so by passing NULL, youā€™re just saying, ā€œIā€™m still working on the same string, so use that pointer you haveā€.

1 Like

Ok, that helps me get a better understanding now.

However, Iā€™m still lost as to why this wonā€™t verify in the code builder.

int setupChannel(String cmd) { // cmd syntax: "channel#,startTime,doseRate, dose" (startTime is sent as hour*3600 + minute*60 + second)
    Serial.println(cmd);
    char *rmdr;
    char *stringArgs = (char*)cmd.c_str();
    int index = atoi(strtok_r(stringArgs, "," &rmdr));
    Channel* c = &channels[index];
    c->onTime = atof(strtok_r(NULL, "," &rmdr));
    c->doseRate = atof(strtok_r(NULL, ","  &rmdr));
    c->numberOfDoses = atoi(strtok_r(NULL, "," &rmdr));
    c->totalDose = atoi(rmdr);
    float dosePerActuation = c->totalDose/c->numberOfDoses;
    float durationPerActuation = (dosePerActuation/c->doseRate) * 60; // assuming doseRate is in volume/minute
    c->offTime = c->onTime + durationPerActuation;

What error are you getting?

BTW, totalDose is a float, not an int, so you should use atof (c->totalDose = atof(rmdr);).

1 Like

Got it! Changed it...here is the error I'm getting

multi-channel_doser_dupli.cpp: In function 'int setupChannel(String)':

multi-channel_doser_dupli.cpp:83:48: error: invalid operands of types 'const char [2]' and 'char*' to binary 'operator&' c->calibrationEnd = 90000;

multi-channel_doser_dupli.cpp:85:42: error: invalid operands of types 'const char [2]' and 'char*' to binary 'operator&' }

multi-channel_doser_dupli.cpp:86:45: error: invalid operands of types 'const char [2]' and 'char*' to binary 'operator&'

multi-channel_doser_dupli.cpp:87:49: error: invalid operands of types 'const char [2]' and 'char*' to binary 'operator&'

It references lines 83-87, so here are those lines.

    int index = atoi(strtok_r(stringArgs, "," &rmdr));
    Channel* c = &channels[index];
    c->onTime = atof(strtok_r(NULL, "," &rmdr));
    c->doseRate = atof(strtok_r(NULL, ","  &rmdr));
    c->numberOfDoses = atoi(strtok_r(NULL, "," &rmdr));

How many arguments do you have in the strtok_r functions now? Look at your syntax, and compare it to what I posted a few posts ago.

1 Like

I currently have three arguments, and I was trying to add a fourth, which you're saying I don't need even though I have four pieces in my string.

I presume this is the post you're referring to?

What stands out in this statement is What's in the parentheses, i.e. the arguments to the function, have nothing to do with how many pieces are in your string.

No, you donā€™t have three arguments, you have two. Look at how many commas you have (not counting the one in quotes).

1 Like

I just needed a clear head, I got it to verify, and it works. Sorry to put you through the frustrationsā€¦but I appreciate the walk through and help.