How to call methode in pic 18F4550 with c language (compiler) - c

update
I'm using pic 18F4550 with microchip v8.63 and C compiler.
I'm trying to make a color sensor. When a led burns a whant to go for example methode red.
In OOP is that simple to go to other methods, but how can you do that in C for microchip?
void main(void)
{
my code here....
// Leds are connected here.
if(PORTBbits.RB4 == 0) { //red
LATDbits.LATD0 = 1;
}
else if(PORTBbits.RB5 == 0) { //green
LATDbits.LATD1 = 1;
}
else if(PORTBbits.RB6 == 0) { //blue
LATDbits.LATD2 = 1;
}
// LDR is connected here.
//
if(PORTAbits.RA0 == 1) {
if(PORTBbits.RB4 == 0) {
int red = PORTBbits.RB1; // test.
colorRed();
}
else if(PORTBbits.RB5 == 0) {
int green = PORTBbits.RB1;
colorGreen();
}
else if(PORTBbits.RB6 == 0) {
int blue = PORTBbits.RB1;
colorBlue();
}
}
}
void colorRed(void)
{
LATDbits.LATD0 = 0;
// other code here
}
void colorGreen(void)
{
LATDbits.LATD1 = 0;
}
void colorGreen(void)
{
LATDbits.LATD2 = 0;
}
These are the errors:
..\code\main.c:56:Warning [2058] call of function without prototype
..\code\main.c:60:Warning [2058] call of function without prototype
..\code\main.c:64:Warning [2058] call of function without prototype
..\code\main.c:69:Error [1109] type mismatch in redeclaration of 'colorRed'
..\code\main.c:74:Error [1109] type mismatch in redeclaration of 'colorGreen'
..\code\main.c:79:Error [1504] redefinition of 'colorGreen'

You simply need to add forward declarations ("prototypes") for the functions before the definition of main.
void colorRed(void);
void colorGreen(void);
void colorBlue(void);
Without these, the compiler assumes a function type of int colorRed(), where int mismatches with void and () mismatches with (void).
Also, as I mentioned in the comments, main should implement an endless loop which checks the chip's inputs and modifies the outputs.

Related

exercism Isogram challenge in C track - running locally but not in exercism

So I recently started with C at exercism page.
I currently facing a rather simple challenge.
Determine if a word or phrase is an isogram.
An isogram (also known as a "non-pattern word") is a word or phrase without a repeating letter, however spaces and hyphens are allowed to appear multiple times.
Examples of isograms:
lumberjacks
background
downstream
six-year-old
The word isograms, however, is not an isogram, because the s repeats.
There are 15 tests in total, of which one specific is not passed:
test_isogram_with_duplicated_hyphen
I guess test number 15 also passes because of some error I don't see
Here's the testing code:
#include "test-framework/unity.h"
#include "isogram.h"
#include <stdlib.h>
void setUp(void)
{
}
void tearDown(void)
{
}
static void test_empty_string(void)
{
TEST_ASSERT_TRUE(is_isogram(""));
}
static void test_null(void)
{
TEST_IGNORE(); // delete this line to run test
TEST_ASSERT_FALSE(is_isogram(NULL));
}
static void test_isogram_with_only_lower_case_characters(void)
{
TEST_IGNORE();
TEST_ASSERT_TRUE(is_isogram("isogram"));
}
static void test_word_with_one_duplicated_character(void)
{
TEST_IGNORE();
TEST_ASSERT_FALSE(is_isogram("eleven"));
}
static void test_word_with_one_duplicated_character_from_end_of_alphabet(void)
{
TEST_IGNORE();
TEST_ASSERT_FALSE(is_isogram("zzyzx"));
}
static void test_longest_reported_english_isogram(void)
{
TEST_IGNORE();
TEST_ASSERT_TRUE(is_isogram("subdermatoglyphic"));
}
static void test_word_with_duplicated_letter_in_mixed_case(void)
{
TEST_IGNORE();
TEST_ASSERT_FALSE(is_isogram("Alphabet"));
}
static void test_word_with_duplicated_letter_in_mixed_case_lowercase_first(void)
{
TEST_IGNORE();
TEST_ASSERT_FALSE(is_isogram("alphAbet"));
}
static void test_hypothetical_isogrammic_word_with_hyphen(void)
{
TEST_IGNORE();
TEST_ASSERT_TRUE(is_isogram("thumbscrew-japingly"));
}
static void
test_hypothetical_word_with_duplicated_character_following_hyphen(void)
{
TEST_IGNORE();
TEST_ASSERT_FALSE(is_isogram("thumbscrew-jappingly"));
}
static void test_isogram_with_duplicated_hyphen(void)
{
TEST_IGNORE();
TEST_ASSERT_TRUE(is_isogram("six-year-old"));
}
static void test_made_up_name_that_is_an_isogram(void)
{
TEST_IGNORE();
TEST_ASSERT_TRUE(is_isogram("Emily Jung Schwartzkopf"));
}
static void test_duplicated_character_in_the_middle(void)
{
TEST_IGNORE();
TEST_ASSERT_FALSE(is_isogram("accentor"));
}
static void test_same_first_and_last_characters(void)
{
TEST_IGNORE();
TEST_ASSERT_FALSE(is_isogram("angola"));
}
static void test_word_with_duplicated_character_and_with_two_hyphens(void)
{
TEST_IGNORE();
TEST_ASSERT_FALSE(is_isogram("up-to-date"));
}
int main(void)
{
UnityBegin("test_isogram.c");
RUN_TEST(test_empty_string);
RUN_TEST(test_null);
RUN_TEST(test_isogram_with_only_lower_case_characters);
RUN_TEST(test_word_with_one_duplicated_character);
RUN_TEST(test_word_with_one_duplicated_character_from_end_of_alphabet);
RUN_TEST(test_longest_reported_english_isogram);
RUN_TEST(test_word_with_duplicated_letter_in_mixed_case);
RUN_TEST(test_word_with_duplicated_letter_in_mixed_case_lowercase_first);
RUN_TEST(test_hypothetical_isogrammic_word_with_hyphen);
RUN_TEST(test_hypothetical_word_with_duplicated_character_following_hyphen);
RUN_TEST(test_isogram_with_duplicated_hyphen);
RUN_TEST(test_made_up_name_that_is_an_isogram);
RUN_TEST(test_duplicated_character_in_the_middle);
RUN_TEST(test_same_first_and_last_characters);
RUN_TEST(test_word_with_duplicated_character_and_with_two_hyphens);
return UnityEnd();
}
This is my code:
#include "isogram.h"
#include <stdlib.h>
#include <stdio.h>
/* gives new char array from input, only small letters */
char* clean_words(char* ptr_input)
{
// new container; everything bigger than 27 is impossible to be an isogram
static char cleaned[27] = {"00000000000000000000000000"};
int i = 0, j = 0, k = 0;
for (int i = 0; ptr_input[i] != '\000'; i++)
{
k++;
}
for (i=0; i <= k; i++, j++)
{
if (ptr_input[i] > 64 && ptr_input[i] < 91)
{
cleaned[j] = ptr_input[i] + 32;
}
else if (ptr_input[i] > 96 && ptr_input[i] < 123)
{
cleaned[j] = ptr_input[i];
}
else
{
j--;
}
}
char* ptr_output = &cleaned[0];
return ptr_output;
}
bool is_isogram(char phrase[])
{
if(phrase == NULL)
{ return false; }
char* ptr_a = clean_words(phrase);
char ca_empty[27] = {"00000000000000000000000000"};
for(int i = 0; i <= 27; i++, ptr_a++){
// first element is always copied
if(i == 0){
ca_empty[i] = *ptr_a;
continue;
}
// '0' is sentinel, meaning the input word is finished => exit loop.
if(*ptr_a == '0' || *ptr_a == '\000')
{ break; }
// following elements only copied if different than current input char
int j = 0;
// loop copied for doubles, exit when found
for(;j<i;j++)
{
if(ca_empty[j] == *ptr_a){
return false;
}
}
// if none was found, copy new letter
ca_empty[i] = *ptr_a;
}
return true;
}
So basically I solve this in 2 steps. First, I will reduce any input to small letters only. Second, I copy letter by letter to a new container and test doubles before every copy process.
Yes, there are certainly fancier solutions, but I'd like to know if anyone can spot why I get FAILED on "six-year-old". Especially, when it is working locally. Thanks! :-)
So I figured it out by myself:
The problem is the helper function clean_words.
The char array cleaned is declared as static. That means it will keep its value even after the current block is finished.
When the tests run through, cleaned will still contain remaining letters of the input from other tests. The solution would be removing the static keywird or implementing a way to clean up the container, like
memset(cleaned, '0', 26);
From https://en.cppreference.com/w/c/language/storage_duration
static storage duration.
The storage duration is the entire execution of the program, and the value stored in the object is initialized only once, prior to main function. All objects declared static and all objects with either internal or external linkage that aren't declared _Thread_local (since C11) have this storage duration.

Reuseable function for looping [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
Question:
I want to create a reusable function, because in my code much line that use same code structure
The code using for example if { if { `Only here's the different` } }. Of course the pattern not same as this, this using as an example.
I've been code using framework such as Laravel, there's a directive called as SLOT
Is there any way I can inject code in the middle of for loop? Or anything same as SLOT inside C programming
Sample code:
void functionname() {
for (int i=0; i < total_count; i++) {
SELECT THE ITEM (i)
if (a == b) return;
if (c) {
CODE INJECT HERE
}
}
}
Forget to mention before, a, b, c and so on from the coding above is getting from ITEM (i)
You should use a callback. i.e. you should send a function pointer (i.e. the address of the function you want to execute) and use that pointer to execute that function inside your loop.
In the example below, p is a pointer to a function taking a const char * for a parameter and returning an int.
int (*p)(const char *s) ;
NB: all functions passed as parameter, to be used as callback must have the same prototype (which is why such functions are often declared taking a generic pointer parameter void * to accept whatever you've got to send to the function).
So with your example and with functions taking void * as a parameter and returning void *, and with param defining a parameter that you want to feed to your function, this gives us the following code:
void functionname(void *(*func)(void *)) {
for (int i=0; i < total_count; i++) {
SELECT THE ITEM (i)
if (a == b) return;
if (c) {
func(&param);
}
}
}
you can call your function wiht whatever function respecting the prototype... For instance:
void *my_custom_function(void *param) {
...
}
...
functionname(my_custom_function);
...
As suggested in the comment by KamilCik, use function pointers:
void functionname(void *fx)(void)) {
for (int i=0; i < total_count; i++) {
SELECT THE ITEM (i)
if (a == b) return;
if (c) {
//CODE INJECT HERE
fx();
}
}
}
And use it like
void foo(void) { puts("foo() called"); }
void bar(void) { puts("bar() called"); }
int main(void) {
functionname(foo);
functionname(bar);
}
For a concrete example:
#include <stdio.h>
int a = 1;
int b = 2;
typedef void (*selector)(int, int *);
typedef void (*injector)(void);
void select1(int x, int *c) { printf("%s: %d\n", __func__, *c = x); }
void select2(int x, int *c) { printf("%s: %d\n", __func__, *c = x); }
void inject1(void) { printf("%s\n", __func__); }
void inject2(void) { printf("%s\n", __func__); }
void
functionname(size_t total_count, selector SELECT_THE_ITEM,
injector CODE_INJECT_HERE )
{
for (size_t i=0; i < total_count; i++) {
int c;
SELECT_THE_ITEM (i, &c);
if (a == b) return;
if (c) {
CODE_INJECT_HERE();
}
}
}
int
main(void)
{
functionname(2, select1, inject1);
functionname(3, select2, inject2);
}
You can do what you ask by defining your "CODE INJECT HERE" as the body of a function, and passing a pointer to that function:
void functionname(void (*inject)(void)) {
for (int i=0; i < total_count; i++) {
SELECT THE ITEM (i)
if (a == b) return;
if (c) {
inject();
}
}
}
void do_something(void) {
CODE INJECT HERE
}
void do_something_else(void) {
OTHER CODE INJECT HERE
}
int main(void) {
functionname(do_something));
functionname(do_something_else));
}
Do note, however, that this is not simple code injection in the same sense as a macro would provide. In particular, the executions of do_something() and do_something_else() will not see the local variables of main() or of functionname(), and the do_* functions can return only from themselves, not from a caller further up the chain. The former can be mitigated to some extent by passing parameters to the do_* functions (which they must be prepared to accept).
Another alternative would be to use a macro instead of a function to provide the common framework. It would look something like this:
#define frame_it(x) do { \
for (int i=0; i < total_count; i++) { \
SELECT THE ITEM (i) \
if (a == b) return; \
if (c) { \
x \
} \
} \
} while (0)
int main(void) {
frame_it(
CODE INJECT HERE
);
frame_it(
OTHER CODE INJECT HERE
);
}
That keeps the CODE INJECT HERE code in the function using it, which might be advantageous if in fact each such piece of code is used in only one place. It also allows both that code and the framing code to access the local variables of the function in which they appear, and to return from that function if desired.
However, macro programming has earned a mostly-deserved reputation for being error prone and difficult to read and debug. Your particular need may be one that is well served by this approach, but do not choose this direction lightly.
Function pointers are great for this. You can typedef the function signatures you'd like to support. Example:
/* A signature for condition checking functions, taking a "void*" argument
and returning true or false */
typedef bool(*cond_check_t)(void*);
/* A signature for functions to execute if a condition is met. This takes a
"void*" argument but you decide what you need */
typedef void(*exec_t)(void*);
You can package these two in a struct to form a nice pair:
typedef struct {
cond_check_t checker;
exec_t executor;
} check_exec_t;
And with that, another struct to keep a bunch of these condition and executor pairs:
typedef struct {
size_t size;
size_t capacity;
check_exec_t *conditionals;
} cond_pack_t;
You then create support functions for adding checkers and executors and a function to processes one of these packaged checkers and executors.
cond_pack_t* cond_pack_create(size_t capacity) {
cond_pack_t* cp = malloc(sizeof(*cp));
if(cp) {
cp->conditionals = malloc(sizeof(*cp->conditionals) * capacity);
if(cp->conditionals) {
cp->size = 0;
cp->capacity = capacity;
} else {
free(cp);
cp = NULL;
}
}
return cp;
}
void cond_pack_destroy(cond_pack_t *cp) {
free(cp->conditionals);
free(cp);
}
bool cond_pack_add(cond_pack_t *cp, cond_check_t checker, exec_t executor) {
if(cp->size == cp->capacity) return false;
cp->conditionals[cp->size].checker = checker;
cp->conditionals[cp->size].executor = executor;
++cp->size;
return true;
}
void cond_pack_process(cond_pack_t *cp) {
for(size_t i = 0; i < cp->size; ++i) {
if(cp->conditionals[i].checker(NULL)) { /* execute checker */
cp->conditionals[i].executor(NULL); /* execute executor */
}
}
}
With that, a usage example could look like this
//---
bool some_check(void *foo) {
return true;
}
void some_executor(void *foo) {
printf("some_executor\n");
}
bool some_other_check(void *foo) {
return false;
}
void some_other_executor(void *foo) {
printf("some_other_executor\n");
}
int main() {
cond_pack_t *cp = cond_pack_create(10);
if(cp) {
cond_pack_add(cp, some_check, some_executor);
cond_pack_add(cp, some_other_check, some_other_executor);
cond_pack_process(cp); /* run all the checkers / executors */
cond_pack_destroy(cp);
}
}
Demo

Updating array in a function causes pointer lose

I am trying to divide my code into functions, I have a sample code of "Game Of Life".
However, when I try to initialize 2D grid array in a function, gnuplot gives no valid data points error.
These are global variables declared before main:
static char **currWorld=NULL, **nextWorld=NULL
This is the original logic to init game grid, but this part is in main.
if (game == 0){ // Use Random input
for(i=1;i<nx-1;i++){
for(j=1;j<ny-1;j++) {
currWorld[i][j] = (real_rand() < prob);
population[w_plot] += currWorld[i][j];
}
}
}
else if (game == 1){ // Block, still life
printf("2x2 Block, still life\n");
int nx2 = nx/2;
int ny2 = ny/2;
currWorld[nx2+1][ny2+1] = currWorld[nx2][ny2+1] = currWorld[nx2+1][ny2] = currWorld[nx2][ny2] = 1;
population[w_plot] = 4;
}
else if (game == 2){ // Glider (spaceship)
printf("Glider (spaceship)\n");
// Your code codes here
}
else {
printf("Unknown game %d\n",game);
exit(-1);
}
This is my function:
int init_game(int choice, int probability){
int i,j;
if (choice == 0){ // Use Random input
for(i=1;i<nx-1;i++){
for(j=1;j<ny-1;j++) {
currWorld[i][j] = (real_rand() < probability);
population[w_plot] += currWorld[i][j];
}
}
}
else if (choice == 1){ // Block, still life
printf("2x2 Block, still life\n");
int nx2 = nx/2;
int ny2 = ny/2;
currWorld[nx2+1][ny2+1] = currWorld[nx2][ny2+1] = currWorld[nx2+1][ny2] = currWorld[nx2][ny2] = 1;
population[w_plot] = 4;
}
else if (choice == 2){ // Glider (spaceship)
printf("Glider (spaceship)\n");
// Your code codes here
}
else {
printf("Unknown game %d\n",choice);
exit(-1);
}
}
and my function call in main:
init_game(game, prob);
value of game is 0, prob is 0.2 and I tested memory allocations and other stuff, they work fine.
Only difference is I moved the logic to a function. How can this happen? My arrays are global, I cannot understand how it cannot be initialized.
This is the gnuplot error:
Skipping data file with no valid points
Since gnuplot and other functions are works fine, I did not add them but if you need any info, I can add.
Here is the link of file itself:
file

How to continually print output inside a switch statement?

I have been trying to continually print the PWM output of pin 3 inside the switch statement condition but it only prints once. Can I continually print it in serial monitor until it meets the second conditon? or use a while loop? or a if else ?
Here is my code I also have a code with a similar function but it uses if else but still it only prints once
void loop() {
// if there's any serial available, read it:
while (Serial.available() > 0) {
int InitVal = Serial.parseInt();
int red = Serial.parseInt();
switch(InitVal) {
case 1:
if (Serial.read() == '\n') {
analogWrite(redPin, red);
Serial.println(red);
Serial.write(red);
}
break;
case 0:
analogWrite(redPin, 0);
Serial.println(0);
Serial.write(0);
break;
}
}
}
I'am planning to inter-phase this with a GUI . A GUI sends ascii to the arduino reads it then sends the output value to the GUI.
Example
1.GUI sends [1,123] : 1 = the trigger point for the switch statement ; 123 = PWM value.
Arduino receives instructions and it prints out the pwm value
GUI receives pwm value and displays it
Revised code: Stuck at the last while loop maybe i could use a threading function in arduino so that the last while loop would be satisfied/dissatisfied?
void loop() {
int InitVal = 0;
// if there's any serial available, read it:
while (Serial.available() > 0) {
int InitVal = Serial.parseInt();
int red = Serial.parseInt();
switch(InitVal) {
case 1:
if (Serial.read() == '\n') {
InitVal = 1;
//analogWrite(redPin, red);
//Serial.println(red);
// Serial.write(red);
}
break;
case 0:
InitVal = 0;
//analogWrite(redPin, 0);
//Serial.println(0);
//Serial.write(0);
break;
}
if (InitVal) /* when enabled, blink leds */ {
delay(20);
while (InitVal == 1) /* loop forever */{
Serial.println(red);
Serial.write(red);
delay(20);
}
}
}
}
I discarded Serial.parseInt() function, removed the switch statments and followed #Arno Bozo advise on serial listening while following this tutorial on http://forum.arduino.cc/index.php?topic=396450.0
I came up with what I want and here is the code
const int redPin = 3;
const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars]; // temporary array for use when parsing
// variables to hold the parsed data
boolean newData = false;
int InitVal = 0; // change to init value or red
int red = 0;
void setup() {
// initialize serial:
Serial.begin(9600);
// make the pins outputs:
pinMode(redPin, OUTPUT);
}
void loop() {
recvWithStartEndMarkers();
if (newData == true) {
strcpy(tempChars, receivedChars);
// this temporary copy is necessary to protect the original data
// because strtok() used in parseData() replaces the commas with \0
parseData();
One();
newData = false;
}
else {
Zero();
}
}
///////////////////// ///////////////////// /////////////////////
void recvWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
while (Serial.available() > 0 && newData == false) {
rc = Serial.read();
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
///////////////////// ///////////////////// /////////////////////
void parseData() { // split the data into its parts
char * strtokIndx; // this is used by strtok() as an index
strtokIndx = strtok(tempChars,","); // get the first part - the string
InitVal = atoi(strtokIndx); // copy it to messageFromPC
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
red = atoi(strtokIndx); // convert this part to an integer
}
///////////////////// ///////////////////// /////////////////////
void One() {
if (InitVal == 0){
delay(20);
Serial.println(0);
delay(20);
}
}
///////////////////// ///////////////////// /////////////////////
void Zero() {
if (InitVal == 1){
delay(20);
Serial.println(red);
delay(20);
}
}
In Summary the code works like this
1.In serial monitor send this <1,123> : 1 = the trigger point for the switch statement ; 123 = PWM value.
Arduino receives instructions and it prints out the pwm value
If you send <0,123> it prints a zero once
I post a refined code here. The architecture may be reused for serial treatment. I have written it as an example for people I meet and who are learning with arduino.
I have made comments and explanation of ways to avoid delay. Here it is used to print current value of pwm every 1s, without stopping with a delay(1000).
#include <Arduino.h>
// with schedule(f,i) , the function f() will be called every i ms
// schedule(f,i) lines are put in loop() function
// f is of type void f(void)
#define schedule(f,i) {static unsigned long l=0;unsigned long c=millis();if((unsigned long)(c-l)>=i){l=c;f();}}
const int ledPin = 13;
void setup() {
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
}
boolean newCommandHasArrived=false, newParsedCommand=false;
String personalSerialBuffer=""; // char[] would be better; but String are so convenient
enum ECommand {ecmdNoPwm=0, ecmdPwm=1, ecmdBad=10 };
ECommand cmd=ecmdNoPwm;
int cmdArg=0;
boolean readSerialBuffer(String &personalSerialBuffer);
boolean parseCommand(String &apersonalSerialBuffer, ECommand &acmd, int &acmdArg);
void executeCommand(ECommand acmd, int &acmdArg);
void printCurrentValue() {Serial.println(String("cval:") + cmdArg);}
void loop() {
// transfer serial buffer in personal buffer
newCommandHasArrived = readSerialBuffer(personalSerialBuffer);
if (newCommandHasArrived) {
newCommandHasArrived = false;
newParsedCommand = parseCommand(personalSerialBuffer, cmd, cmdArg);
}
if (newParsedCommand) {
newParsedCommand = false;
executeCommand(cmd, cmdArg);
}
// I print current value every 1000ms
//delay(1000); // you can often use delay without pb, but it is a bad usage
// Here I provide you with a quick way to execute a task every 1000ms
{
const unsigned long delayBetweenExecution=1000;
static unsigned long lastTime=0;
unsigned long current = millis();
// note that C++ says that overflow on unsigned is well defined
// it calculates modulo arithmetic
if ((unsigned long)(millis() - lastTime) >= delayBetweenExecution) {
lastTime = current;
Serial.println(String("cval:") + cmdArg);
}
}
// We can make it shorter thanks to a macro:
// but you have to define a void function(void) that uses only global variable
// because it has no argument :
// void printCurrentValue() {Serial.print(String("cval:") + cmdArg);}
//schedule(printCurrentValue, 1000);
}
boolean readSerialBuffer(String &personalSerialBuffer) {
if (Serial.available() > 0) {
personalSerialBuffer.concat(Serial.readString());
}
// the frame is considered finished, if it ends with \n
if (personalSerialBuffer.endsWith("\n"))
return true;
else
return false;
}
boolean parseCommand(String &apersonalSerialBuffer, ECommand &acmd, int &acmdArg) {
// format [ 1, 123]\n
// I omit [ then I read first int : 1
// Note: I cannot detect if no int is found because it will return 0 that is a valid cmd
int readCmd = apersonalSerialBuffer.substring(1).toInt();
// conversion readCmd to acmd
switch (readCmd) {
case 0:
acmd = ecmdNoPwm; break;
case 1:
acmd = ecmdPwm; break;
default:
Serial.println(String("new command unknown: ") +
apersonalSerialBuffer);
apersonalSerialBuffer = "";
return false;
}
// find beginning of 2nd part, separated by ','
int sepPos = apersonalSerialBuffer.indexOf(',');
// no ',' : indexOf returns -1
if (sepPos == -1) {
Serial.println(String("new command could not be parsed: ") +
apersonalSerialBuffer);
apersonalSerialBuffer = "";
return false;
}
// Note: I cannot detect if no int is found because it will return 0 that is a valid cmd
acmdArg = apersonalSerialBuffer.substring(sepPos+1).toInt();
// All is fine
// I have to reset buffer before leaving
apersonalSerialBuffer = "";
return true;
}
void executeCommand(ECommand acmd, int &acmdArg) {
switch(acmd) {
case ecmdNoPwm:
// I erase acmdArg
acmdArg = 0;
analogWrite(ledPin, acmdArg);
Serial.println("cmd no pwm");
break;
case ecmdPwm:
analogWrite(ledPin, acmdArg);
Serial.print("cmd pwm:"); Serial.println(acmdArg);
break;
default:
analogWrite(ledPin, 0);
Serial.println("Bad cmd");
}
}

Error with bool function

I am a new C developer (I am used to programming in Java), and have tried create, what I thought was a simple bool function. Although I am getting an error which I don't understand how to fix:
#include <stdio.h>
#include <stdlib.h>
typedef enum { false, true } bool;
int main() {
int currentNumber, round = 1;
printf("Numbers generated will be between 1 and 20. \n");
currentNumber = rand() % 20;
bool validNumber = false;
do {
if(currentNumber != 0) {
validNumber == true;
} else {
currentNumber = rand() % 20;
}
}while(validNumber == false);
printf("You're on round" + ("%d", round));
printf("You're current number is: " + ("%d", currentNumber));
printf("Higher or Lower (H/L)?");
char userInput [20];
scanf("%s", &userInput);
if((userInput[0] == 'h') || (userInput[0] == 'H')) {
completeRound(round, 'H', currentNumber);
} else if((userInput[0] == 'l') || (userInput[0] == 'L')) {
completeRound(round, 'L', currentNumber);
}
}
void completeRound(int round, char input, int currentNumber) {
int initialVal = currentNumber, newVal;
if(input == 'H') {
newVal = rand() % 20;
bool checkResult(initialVal, newVal, input);
} else {
newVal = rand() % 20;
bool checkResult(initialVal, newVal, input);
}
}
bool checkResult(int initialVal, int finalVal, char input);
bool checkResult(int initialVal, int finalVal, char input) {
if(input == 'H') {
if(initialVal <= finalVal) {
return true;
} else {
return false;
}
}
if(input == 'L') {
if(initialVal >= finalVal) {
return true;
}else {
return false;
}
}
printf("An error has occurred! Aborting game...");
return false;
}
The error is as follows:
\main.c|39|error: conflicting types for 'checkResult'
At first, I thought that for some reason, in C you could only pass certain data types as arguments to a bool method, although I can not find a straight answer to this on Google. Other than that; I can not understand what it means by "conflicting types" (this is the first time I've debugged a C program.
The function I have used to call checkResult is as follows:
Before calling the function you need to write its prototype also. By default compiler is considering it as return type of int but actually it is bool.
so write bool checkResult(int initialVal, int finalVal, char input) before calling checkResult.
You probably have a typo in your code. The line
bool checkResult(initialVal, newVal, temp);
implicitly creates a prototype for a bool function. The types of the arguments are omitted and default to int in C versions prior to C99. This declaration is in conflict with the actual declaration, whose third parameter is of type char.
You probably meant something like this:
bool okay = checkResult(initialVal, newVal, temp);
This defines a bool variable okay and initialises it with the result of the function call. (But note that this variable is local to the current scope, so in your example you'd lose the result immediately.)
It is legal in C to declare a function inside a function body, although it is not good practice. It is more usual to declare them in headers or at the beginning of the file.
As of C99, implicit function declarations are invalid. There also isn't a default argument or function return type of int. You might consider to enforce the C99 standard (eg with -std=c99in gcc) to avoid falling into the implicit-declaration trap.
You have called functions before declaring them.So is the error. Because by default the return type of a c function is "int".
Add
void completeRound(int , char , int );
and
bool checkResult(int , int , char);
after your typedef (better this way than declaring them in body of the calling function).
And since checkResult() is returning a value of type bool you better assign it to a variable of type bool like
bool okay = checkResult(initialVal, newVal, temp); this.

Resources