Check only last 3 digits of sensor output - c

I have a library from WiringPi for DHT11 sensor and I need to modify condition which checks if the value read from sensor is good.
Sometimes the library reads bad values which are 255.255,255.255 or 55,255.255 etc.
sample output
There is the condition in the library:
if(counter==255)
break;
But it doesn't work if the value is e.g. 55,255.255
How can I modify this condition the check last 3 digits of output?
If the output is wrong, there are always "255" at the end of value.
I tried to add conditions like
if(counter==255)
break;
else if(counter==255.255)
break;
But it doesn't solve all possible situations and I realy don't know anything about C/C++
Here is the whole library:
#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define MAX_TIME 85
#define DHT11PIN 7
#define ATTEMPTS 5
int dht11_val[5]={0,0,0,0,0};
int dht11_read_val()
{
uint8_t lststate=HIGH;
uint8_t counter=0;
uint8_t j=0,i;
for(i=0;i<5;i++)
dht11_val[i]=0;
pinMode(DHT11PIN,OUTPUT);
digitalWrite(DHT11PIN,LOW);
delay(18);
digitalWrite(DHT11PIN,HIGH);
delayMicroseconds(40);
pinMode(DHT11PIN,INPUT);
for(i=0;i<MAX_TIME;i++)
{
counter=0;
while(digitalRead(DHT11PIN)==lststate){
counter++;
delayMicroseconds(1);
if(counter==255)
break;
}
lststate=digitalRead(DHT11PIN);
if(counter==255)
break;
// top 3 transistions are ignored
if((i>=4)&&(i%2==0)){
dht11_val[j/8]<<=1;
if(counter>16)
dht11_val[j/8]|=1;
j++;
}
}
// verify checksum and print the verified data
if((j>=40)&&(dht11_val[4]==((dht11_val[0]+dht11_val[1]+dht11_val[2]+dht11_val[3])& 0xFF)))
{
printf("%d.%d,%d.%d\n",dht11_val[0],dht11_val[1],dht11_val[2],dht11_val[3]);
return 1;
}
else
return 0;
}
int main(void)
{
int attempts=ATTEMPTS;
if(wiringPiSetup()==-1)
exit(1);
while(attempts)
{
int success = dht11_read_val();
if (success) {
break;
}
attempts--;
delay(500);
}
return 0;
}

No single variable in your code can hold "255.255", that would require a string or a float. You are obviously referring to the output of
printf("%d.%d,%d.%d\n",dht11_val[0],dht11_val[1],dht11_val[2],dht11_val[3]);.
This printf can never produce a three-value output like 55,255.255.
I assume that your output would be 55.255,255.255.
This in turn means that in case of error you will find the "last three digits" in dht11_val[3].
If my assumption is not correct please provide much more detail on the error circumstances.
On the other hand, I suspect that looking for that value is not the solution for your problem either. The function is more complicated. The value of 255 seems the result of an endless loop which is detected by breaking early at counter = 255. So I am pretty sure that checking "the last three digits" is a LESS precise check than what is already implemented.

Related

What is wrong with my loop? I've tried everything

I'm doing a final project right now and I have the following code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
int main(void){
int day;
int year;
int month;
int daynum=0;
int days=365;
printf("\nPlease input what year you would like to meet\n");
scanf("%d",&year);
printf("\nPlease input what month you would like to meet\n");
scanf("%d",&month);
printf("\nPlease input what day you would like to meet\n");
scanf("%d",&day);
//Later in the code i have the following loop
int k=month;
do {
k--;
switch (k) {
case 0:
case 2:
case 4:
case 6:
case 7:
case 9:
case 11:
daynum=daynum+31;
printf("\nadded 31");
break;
case 1:
if (days==365) {
daynum=daynum+28;
}
else if (days==366) {
daynum=daynum+29;
}
printf("\nadded 28/29");
break;
case 3:
case 5:
case 8:
case 10:
daynum=daynum+30;
printf("\nadded 30");
break;
default:
printf("\nsomething went wrong");
}
}while(k>=0);
return 0;
}
I've tried essentially the same thing with a while and for loop but every time the only thing that shows up in the console is something went wrong. I even tried checking the value of k before the loop and it says it is equal to month. I've also tried setting k equal to a number and it works just fine with that, but i need it to equal month. I really have no idea whats wrong and any help would be appreciated.
The problem is that you're decrementing k at the beginning of the loop body, but checking it at the end of the loop. So on the last iteration you'll decrement it to -1, print the error message, and then stop the loop.
Change the condition to while(k > 0).
Well, I believe you now know the error as #Barmar wrote.
Anyway I add:
always, I mean always, check for the return of scanf(): there is no point in letting the program go if some of the values are not read. scanf() always returns the number of specifiers read, that things that starts with a single %. In your case it will be 1, 0 or -1.
about this
do {
k--;
switch (k) {
you can always switch(--k) with the same effect.
you could state the purpose of the code and provide at least one test value. If you are trying to get the number of days up to and including the user supplied one, you could have made it clear. I was just guessing.
note that Excel or Google sheets can operate on dates so it is a good free reliable check point.
a small change on the default label, like
printf("\n==> daynum is %d, k is %d and something went wrong\n", daynum, k);
would have print
==> daynum is 365, k is -1 and something went wrong
and it would be very helpful. Far better than just write something went wrong. make your program work for you.
you do not need a switch to compute always the same values. Use a table. And as the only change in days is in February just add the extra day there as we always do...
char days_in_month[] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
days_in_month[1] += ( year % 4 == 0 && year % 100 != 0 ) || year % 400 == 0; // 1 or 0
use the command line for the arguments. It is a bit boring enter the program name and then 3 parameters in 3 lines just to see a resulting number.
Honestly have no idea what was the issue with my code, but i moved this section of code further up and its working as intended now. Somewhere months was getting reset to 0 before the loop despite this being the first time i referenced it besides in printf statements. thank you to #dbush who helped me find out the issue.

create program modes using #if in c

I am trying to create two modes for a program using #if and #define but the second mode isn't working why is that ?
I would aslo appreciate it if you could suggest a better way to do this.
Here's my code:
#include "Types.h"
#include <stdio.h>
void main (void)
{
u32 m;
u32 flag = 1;
do
{
printf("\nWelcome\nPress 1 for Admin mode\nPress 2 for User Mode\nYour Choice:");
scanf("%d",&m);
if (m==1)
{
#define m 1
flag = 0;
}
else if (m==2)
{
#define n 2
flag = 0;
}
else
{
printf("\nInvalid number \nPlease Try again");
}
}while(flag);
//using conditional directive to run only the portion of the code for the slected mode
#if m==1
printf("Welcome to admin mode");
#elif n==2
printf("Welcome to user mode");
#endif
}
The #define and ifs are part of the preprocessor macro.
One way to think about them is to imagine the compiler going through your files and cutting and pasting in them as an early step in compilation. When you define for example PI to be 3, it will paste 3's everywhere in your code that you have written the PI. This then tells us that it won't matter which branch of m == 1 or 2 we go down when running the program - all the preprocessor editing has already been completed!
One way to get the program built in a certain mode would be to use a flag when compiling, for example -D DEBUG. Note that we cannot use this to select mode in an already compiled program.
Preprocessor Options:
-D=
Adds an implicit #define into the predefines buffer which is read before the source file is
preprocessed.
The preprocessor if #if can only interpret values which are known at proprocessing time, which is even before compile time.
It cannot read values from variables like your u32 m.
On the other hand, a preprocessor #define is also only done at preprocessing time, it will not be influenced by being within the "then" branch or the "else" branch of an if.
Doing #defines within code blocks (e.g. if branches), or even within a function, is there for not recommended.
You did not specify how your code misbehaves, but I would not be surprised, if the #if always acts admin mode. There has been a #define m 1 before in the file (no matter what path runtime execution took), so the proprocessor will take the first option.
In the C language, al the directives starting with "#" are used by the preprocessor. The preprocessor scans your file before compilation so that "variable" m is hardcoded and you can't change it in runtime (when you're running the program).
Also, the "m" variable is declared but not used.
To change the behaviour of the program on runtime, you should use a standard variable and use a switch-case to check for the variable's value and run the appropriate code.
I would also recommend using standard types defined by the language like "int" or "char" as they have better portability through the different architectures.
Your code could be like this
#include <stdio.h>
int main (void)
{
int m;
do
{
printf("\nWelcome\nPress 1 for Admin mode\nPress 2 for User Mode\nYour Choice:");
scanf("%d",&m);
if (m == 1)
{
printf("Welcome to admin mode");
return 0;
}
else if (m == 2)
{
printf("Welcome to user mode");
return 0;
}
else
{
printf("\nInvalid number \nPlease Try again");
}
}while(m != 1 || m != 2);
return 0;
}

How to use isdigit() for a pin while loop [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
This program accepts any four digit number as the pin , so i used a strlen() to find out whether the pin is has four characters, but I need to make sure that user enters four numbers, how do I use isdigit() before the loop and for the loop condition?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
char pin [4];
printf("Please enter your pin : \n") ;
scanf("%4s" , &pin) ;
system("cls") ;
while (strlen(pin) != 4) {
count = count + 1 ;
if(count < 3){
printf("Invalid Pin \n") ;
printf("Please enter your pin again \n") ;
scanf("%4s", &pin) ;
system("cls");
}
else if (count == 3){
printf("Sorry you can't continue , Please contact your bank for assistance !") ;
return 0 ;
}
}
There are so many issues with this code I may not have covered every one of them in this answer:
Where is your main function? You can't have code outside a function; that doesn't work. C code other than global variable declarations, assignments to constant values, typedefs, struct and enum definitions, must go in a function. In your case you probably want the main function to house the code starting at line 6.
When calling scanf with a string argument, don't take the address of the string - the array is a reference in and of itself.
Calling strlen(pin) before any value has been copied into pin is 100% undefined behavior. Since the memory is uninitialized the strlen function will keep looking for a null character and possibly go out of the array bounds.
C strings are null-terminated. When you declare a string intended to hold n characters, you need to declare the array with a size of n+1 to have room for the null character.
First to answer your question
I would write a helper function 'validatePin' which would check the pin length and validate that the pin is a numeric pin, you can extend this function to do any other validation you require. It might look something like the following
const int PIN_OK = 0;
const int PIN_INVALID_LEN = -1;
const int PIN_INVALID_CHARS = -2;
int validatePin(const char *pin)
{
// Valdiate PIN length
if (strlen(pin) != 4) return PIN_INVALID_LEN;
// Validate PIN is numeric
for (int i = 0; i < 4; ++i)
{
if (!isdigit(pin[i])) return PIN_INVALID_CHARS;
}
return PIN_OK;
}
Then you can adjust your while loop to look something like the following
while (validatePin(pin) != PIN_OK)
{
....
}
Other points regarding your code.
Your char buffer used for scanf does not account for the null terminator. You need to increase the buffer size.
The char array is already giving you the address of the buffer, there is no need to use & to take the address of the char array in scanf.
I have not run your code, so there might be other issues that I missed at first glance.
There are a number of ways to go about doing what you need to do. You can either check your input length, or just validate what it is you have read, your choice. One approach would be:
#include <stdio.h>
#include <ctype.h>
enum { TRIES = 3, NPIN };
int main (void) {
char pin[NPIN+1] = "";
size_t tries = 0, pinok = 0;
for (; tries < TRIES; tries++) { /* 3 tries */
printf ("Please enter your pin : ");
if (scanf (" %4[^\n]%*c", pin) == 1) { /* read pin */
pinok = 1;
size_t i;
for (i = 0; i < NPIN; i++) /* validate all digits */
if (!isdigit (pin[i]))
pinok = 0;
if (pinok) /* if pin good, break */
break;
}
}
if (!pinok) { /* if here and not OK, call bank */
fprintf (stderr, "Sorry you can't continue, Please contact "
"your bank for assistance.\n") ;
return 1;
}
printf ("\n correct pin : %s\n\n", pin); /* your pin */
return 0;
}
(note: to protect against an excessively long string entered at one time, you should empty stdin at the end of the outer for loop each iteration)
Example Use/Output
Failed case:
$ ./bin/pin
Please enter your pin : a555
Please enter your pin : 555a
Please enter your pin : 55a5
Sorry you can't continue , Please contact your bank for assistance.
Successful case:
$ ./bin/pin
Please enter your pin : 2345
correct pin : 2345
Look it over an let me know if you have any questions.

Galton Box/Bean Machine-C

I want to code a simple bean machine program. The program will accept user input for the number of balls and the number of slots, and will calculate the path of each ball. The number of balls in each slot will be printed as a histogram as well.
I tried my best to keep the code short and sweet, yet the best I have managed is 112 lines long. When I ran my code, I received no errors. However, the output seems to have run into some sort of an infinity loop (The '#' symbol which was used to represent numbers in the histogram keeps on printing forever for some reason unknown to me).
Apparently, there is something wrong with my logic somewhere... or a silly little mistake in syntax(but it would have shown up as error, wouldn't it?)... In a nutshell, I cannot figure out exactly what is the problem. (I attempted to walk through the whole code process from start to finish, but my mind kept getting tangled up somewhere in the middle of the code, nowhere near the end of the code either).
Where exactly does my logic go wrong?(Or have I taken the wrong approach to the whole problem?) I do not wish to know the correct code, so that I am able to learn during the whole process of re-editing my code.
Any help (hopefully no model-code answers though), even as a single comment, is tremendously appreciated! :)
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <conio.h>
#include <stdbool.h>
#include <time.h>
//Pls excuse my extensive use of libraries even though I don't really use them
int intchecker(float x)
{
if (floor(x)==x && ceilf(x)==x)
{
return 0;
}
else {
return 1;
}
}
int main(){
char line[] = " +----+----+----+----+----+----+----+----+----+----+---+";
char numbers[] = " 0 5 10 15 20 25 30 35 40 45 50";
float balls,slots;
int slotarry[9],tlevel,ballnum,column,lcounter=0,slotsduplicate=1,y;//tlevel-number of levels in the triangle
srand(time(NULL));
int r;
printf("==========================================================\nGalton Box Simulation Machine\n==========================================================\n");
printf("Enter the number of balls [5-100]: ");
scanf("%f",&balls);
while (balls>100 || balls<5) {
printf("\nInput is not within the range. Please try again.");
printf("\nEnter the number of balls [5-100]: ");
scanf("%f",&balls);
}
while (intchecker(balls)==1) {
printf("\nInput is not an integer. Please try again.");
printf("\nEnter the number of balls [5-100]: ");
scanf("%f",&balls);
}
printf("Enter the number of slots [2-10] : ");
scanf("%f",&slots);
while (slots>10 || slots<2) {
printf("\nInput is not within the range. Please try again.");
printf("\nEnter the number of slots [2-10] : ");
scanf("%f",&slots);
}
while (intchecker(slots)==1) {
printf("\nHow can there be a fraction of a slot? Please re-enter slot number.");
printf("\nEnter the number of slots [2-10] : ");
scanf("%f",&slots);
}
tlevel=slots-1;
for(ballnum=1,column=0;balls>0;balls--,ballnum++,column++){
if (column%5==0){
printf("\n");
}
if (ballnum<10){
printf("[0%d]",ballnum);
}
else{
printf("[%d]",ballnum);
}
for(;tlevel>0;tlevel--){
r = rand() % 2;
if (r==0){
printf("R");
}
else {
printf("L");
lcounter++;
}
}
slotarry[lcounter]++;
tlevel=slots-1;
lcounter=0;
printf(" ");
}
printf("\n\n%s",numbers);
printf("%s",line);
char line2[] = "\n +----+----+----+----+----+----+----+----+----+----+---+";
for(;slotsduplicate<=slots;slotsduplicate++){
if (slotsduplicate<10){
printf("0%d|",slotsduplicate);
}
else{
printf("%d|",slotsduplicate);
}
y=slotarry[slotsduplicate];
if (y==0){
printf(" 0");
}
else{
for (;y>0;y--){
printf("#");
}
printf(" %d",slotarry[slotsduplicate]);
}
printf("%s",line2);
}
return 0;
}
Note:This is not completely error-free. This is just my first draft. I just wish to find out why there is an infinite loop.
Here's how I found the problem. First of all, I think it is a bit of a code smell to have a for loop without anything in the initial assignment section. Couple that with the fact that it seems to print # forever, and it looks like y has a garbage value at the beginning of the loop to print the #s.
So I ran your code in the debugger and paused it when it started printing loads of hashes. I checked the value of y and sure enough it was some unfeasibly high number.
Then I checked where y comes from and found you get it from slotarray. I printed it in the debugger and found that all the values in it were unfeasibly high or massively negative numbers. Obviously, slotarray wasn't being initialised correctly, so I looked for where it was initialised and bingo!
Stack variables (of which slotarray is one) must be explicitly initialised in C. I fixed your code with a call to memset.
The whole debugging process I have just outlined took something less than a minute.
ETA As #EOF points out, there is another bug in that slotarray is defined to contain nine slots (indexed 0 - 8) but you allow people to enter 10 slots. This is a buffer overflow bug.

C RS232 comm. How to compare CPU time?

First time posting so there's probably gonna be more info than necessary but I wanna be thorough:
One of our exercises in C was to create sender and receiver programs that would exchange data via RS232 serial communication with null modem. We used a virtual port program (I used the trial version of Virtual Serial Port by eltima software if you want to test). We were required to do 4 versions:
1) Using a predetermined library created by a previous student that had sender and reveiver etc. premade functions
2) Using the inportb and outportb functions
3) Using OS interrupt int86 and giving register values through the REGS union
4) Using inline assembly
Compiler: DevCPP (Bloodshed).
All worked, but now we are required to compare all the different versions based on the CPU time that is spent to send and receive a character. It specifically says that we have to find the following:
average, standard deviation, min, max and 99,5 %
Nothing was explained in class so I'm a little lost here...I'm guessing those are statistical numbers after many trials of the normal distribution? But even then how do I actually measure CPU cycles on this? I'll keep searching but I'm posting here in the mean time 'cause the deadline is in 3 days :D.
Code sample of the int86 version:
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#define RS232_INIT_FUNCTION 0
#define RS232_SEND_FUNCTION 1
#define RS232_GET_FUNCTION 2
#define RS232_STATUS_FUNCTION 3
#define DATA_READY 0x01
#define PARAM 0xEF
#define COM1 0
#define COM2 1
void rs232init (int port, unsigned init_code)
{
union REGS inregs;
inregs.x.dx=port;
inregs.h.ah=RS232_INIT_FUNCTION;
inregs.h.al=init_code;
int86(0x14,&inregs,&inregs);
}
unsigned char rs232transmit (int port, char ch)
{
union REGS inregs;
inregs.x.dx=port;
inregs.h.ah=RS232_SEND_FUNCTION;
inregs.h.al=ch;
int86(0x14,&inregs,&inregs);
return (inregs.h.ah);
}
unsigned char rs232status(int port){
union REGS inregs;
inregs.x.dx=port;
inregs.h.ah=RS232_STATUS_FUNCTION;
int86(0x14, &inregs, &inregs);
return (inregs.h.ah); //Because we want the second byte of ax
}
unsigned char rs232receive(int port)
{
int x,a;
union REGS inregs;
while(!(rs232status(port) & DATA_READY))
{
if(kbhit()){
getch();
exit(1);
}
};
inregs.x.dx=port;
inregs.h.ah=RS232_GET_FUNCTION;
int86(0x14,&inregs,&inregs);
if(inregs.h.ah & 0x80)
{
printf("ERROR");
return -1;
}
return (inregs.h.al);
}
int main(){
unsigned char ch;
int d,e,i;
do{
puts("What would you like to do?");
puts("1.Send data");
puts("2.Receive data");
puts("0.Exit");
scanf("%d",&i);
getchar();
if(i==1){
rs232init(COM1, PARAM);
puts("Which char would you like to send?");
scanf("%c",&ch);
getchar();
while(!rs232status(COM1));
d=rs232transmit(COM1,ch);
if(d & 0x80) puts("ERROR"); //Checks the bit 7 of ah for error
}
else if(i==2){
rs232init(COM1,PARAM);
puts("Receiving character...");
ch=rs232receive(COM1);
printf("%c\n",ch);
}
}while(i != 0);
system("pause");
return 0;
}
There is some guesswork required here because the question is a little undefined.
You've listed four different methods for sending/receiving a character. What I suspect your lecturer is looking for is the time from when you call the method given (or enter your inline assembly code) to the time when you return from the method (leave inline code). You will need to grab a time just before the call and just after the call and find their difference.
Less ambiguous is cpu time. The clock() method is the most straightforward way to do this, however this may not be what the lecturer is looking for.
Finally are the statistics, which is straightforward. Do a bunch of runs, and run some statistics on the times

Resources