Math calculations in arduino - arduino-uno

I wrote a code to do a basic calculations with arduino uno. but it returns me a wrong answer for filledPercentage. It is always -1. what is the problem with this?
//include the library code:
#include <LiquidCrystal.h>
// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
const int rs = 13, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
int lowLevelDistance =112;
int highLevelDistance = 47;
void setup() {
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
Serial.begin(9600);
}
void loop() {
// set the cursor to column 0, line 1
// (note: line 1 is the second row, since counting begins with 0):
lcd.setCursor(0, 1);
int currentLevel = 101;
int filledLevel = (lowLevelDistance - currentLevel);
int fullLevel = (lowLevelDistance - highLevelDistance);
int filledPercentage = filledLevel / (fullLevel / 100);
Serial.println(lowLevelDistance);
Serial.println(highLevelDistance);
Serial.println(currentLevel);
Serial.println(filledLevel);
Serial.println(fullLevel);
Serial.println(filledPercentage);
delay(1000);
}

You shouldn't use an integer for the division, your fulllevel / 100 returns 0.65 but then is converted into an integer (truncating it into a 0).
Dividing by 0 throws an error (-1).

Related

Reduce the use of DigitalWrite()

I'm currently doing a circuit which has two seven segment display. Is there any codes to lessen the usage of digitalwrite()? your text
I also found some codes in arduino for a single seven segment to reduce the digitalwrite.
Here is my code
int E1 = 13;
int E2 = 12;
int D1 = 11;
int D2 = 10;
int C1 = 9;
int C2 = 8;
int G1 = 7;
int G2 = 6;
int F1 = 5;
int F2 = 4;
int a1 = 3;
int a2 = 2;
int b1 = 1;
int B2 = 0;
//setting up the pin
void setup()
{
pinMode(E1, OUTPUT);
pinMode(E2, OUTPUT);
pinMode(D1, OUTPUT);
pinMode(D2, OUTPUT);
pinMode(C1, OUTPUT);
pinMode(C2, OUTPUT);
pinMode(G1, OUTPUT);
pinMode(G2, OUTPUT);
pinMode(F1, OUTPUT);
pinMode(F2, OUTPUT);
pinMode(a1, OUTPUT);
pinMode(a2, OUTPUT);
pinMode(b1, OUTPUT);
pinMode(B2, OUTPUT);
}
byte pinNumArr [7]{A1, B1, C1, D1, E1, F1,G1};
byte number7S [10] [7] =
{
{HIGH,HIGH,HIGH,HIGH,HIGH,HIGH, LOW}, // Number 0
{LOW,HIGH,HIGH,LOW,LOW,LOW, LOW}, // Number 1
{HIGH,HIGH,LOW,HIGH,HIGH,LOW,HIGH}, // Number 2
{HIGH,HIGH,HIGH,HIGH,LOW,LOW,HIGH}, // Number 3
{LOW,HIGH,HIGH,LOW,LOW,HIGH,HIGH}, // Number 4
{HIGH,LOW,HIGH,HIGH,LOW,HIGH,HIGH}, // Number 5
{HIGH,LOW,HIGH,HIGH,HIGH,HIGH,HIGH}, // Number 6
{HIGH,HIGH,HIGH,LOW,LOW,LOW,LOW}, // Number 7
{HIGH,HIGH,HIGH,HIGH,HIGH,HIGH,HIGH}, // Number 8
{LOW,HIGH,HIGH,HIGH,LOW,HIGH,HIGH} // Number 9
};
void displayNumber(byte value = 0 )
{
for (int idx = 0; idx < 7; idx++)
{
digitalWrite(pinNumArr[idx], number7S[value][idx]);
value = number7S[value][idx];
}
};
void loop()
{
displayNumber();
delay(500);
}
I want to lessen the usage of digitalwrite for double seven segment display
You can do direct port manipulation instead of all those digitalWrite().
Digital pins 0-7 are on PORTD and digital pins 8-13 are on PORTB.
You can set all of the pins in one line like this:
PORTB = B00000000; //Set pin 8-13 LOW
or you could say:
PORTB = B00010100; //Set pin 10 and 12 HIGH, all others low

Printing the output data of a turbidity sensor with Arduino UNO

I am reading the output in voltage of a turbidity sensor : https://www.dfrobot.com/product-1394.html?tracking=5b603d54411d5 with an Arduino UNO. I want to print the value of volts outage and its NTU (turbidity units) on an LCD screen ADM1602U Sparkfun.
I cant seem to print the dtata correctly on the lCD, it opens and lights up (so I think the wiring is ok) but no data appear.
Here is the code I am using:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 16, 2);
int sensorPin = A0;
int val = 0;
float volt;
float ntu;
void setup()
{
Serial.begin(9600);
lcd.init();
// Turn on the blacklight and print a message.
lcd.backlight();
}
void loop()
{
volt = ((float)analogRead(sensorPin)/1023)*5;
ntu = -1120.4*square(volt)+5742.3*volt-4353.8;
val = analogRead(volt);
Serial.println(volt);
lcd.clear();
lcd.setCursor(0,0);
lcd.print(volt);
lcd.print(" V");
lcd.setCursor(0,1);
lcd.print(ntu);
lcd.print(" NTU");
delay(10);
}
float round_to_dp( float in_value, int decimal_place )
{
float multiplier = powf( 10.0f, decimal_place );
in_value = roundf( in_value * multiplier ) / multiplier;
return in_value;
}
I used an analogread just to see if I was getting correct voltage values for the sensor and I am.
Thanks
Ok so I found the answer, the libary used was not appropriate to print on a 16x2 LCD display. The following code worked FYI:
#include <Wire.h>
#include <SoftwareSerial.h>
// Set the LCD address to 0x27 for a 16 chars and 2 line display
SoftwareSerial LCD(10, 11); // Arduino SS_RX = pin 10 (unused), Arduino SS_TX = pin 11
int sensorPin = A0;
float volt;
float ntu;
void setup()
{
Serial.begin(9600);
LCD.begin(9600); // set up serial port for 9600 baud
delay(500); // wait for display to boot
}
void loop()
{
volt = ((float)analogRead(sensorPin)/1023)*5;
ntu = -1120.4*square(volt)+5742.3*volt-4352.9;
Serial.println(volt);
// move cursor to beginning of first line
LCD.write(254);
LCD.write(128);
// clear display by sending spaces
LCD.write(" ");
LCD.write(" ");
// move cursor to beginning of first line
LCD.write(254);
LCD.write(128);
LCD.print(volt);
LCD.write(" V");
LCD.write(254);
LCD.write(192);
LCD.print(ntu);
LCD.write(" NTU");
delay(1000);
}

How to set a binary int?

I am new to coding in C using a Arduino Uno. I would like to do the following:
int randomNumber;
int randomNumberBinairy = 0;
void setup() {
Serial.begin(9600);
randomSeed(analogRead(A0));
}
void loop() {
randomNumber = random(1, 16);
randomNumberBinairy = ((randomNumber, BIN));
Serial.println(randomNumberBinairy);
delay(5000);
}
This prints out:
2
2
2
2
etc..
However I would like it to print out the random number (between 1 and 16) in binary. So it should look something like:
101
1100
110
10
etc..
Any help on this please?
in arduino you can use the function bitRead(x, n)
int randomNumber;
void setup() {
Serial.begin(9600);
randomSeed(analogRead(A0));
}
void loop() {
randomNumber = random(1, 16);
Serial.print(bitRead(randomNumber, 0));
Serial.print(bitRead(randomNumber, 1));
Serial.print(bitRead(randomNumber, 2));
Serial.println(bitRead(randomNumber, 3));
delay(5000);
}
Just for your own reference, the documentation of Serial.print says:
Serial.print(78, BIN) gives "1001110"
Serial.print(78, OCT) gives "116"
Serial.print(78, DEC) gives "78"
Serial.print(78, HEX) gives "4E"
That is, if you want to print something in binary then you only need
to write
Serial.print(randomNumber, BIN);
or
Serial.println(randomNumber, BIN);
It's simple as that.
If you are sure it will be always 0 to 15 you can write a switch-case block that handles 16 different probability. That works faster than bitread(x, n) for each bit.

How can I check if there is only value changed in a (bitwise?) value?

How can I check if there is only 1 bit change between a value and another (next) value?
the output is for example
001
101
110
in the second output there is a 0 changed into a 1
in the third output there is a 0 changed into a 1 AND also the last 1 changed into a 0
the program may only continue if there is only 1 change.
First, XOR the two numbers. XOR will return a 1 for every bit that changed.
Example:
0101110110100100
XOR
0100110110100100
would give you
0001000000000000
Now what you need is a quick way to check if there is only a single bit in your resulting number, or in other words, if the resulting number is a power of two.
A quick test for that is: (x & (x - 1)) == 0.
No for loops needed.
You can compute the bitwise XOR and then just count the bits that are 1's. This is known as the Hamming distance. For example:
unsigned int a = 0b001;
unsigned int b = 0b100;
unsigned int res;
/* Stores the number of different bits */
unsigned int acc;
res = a ^ b;
/* from https://graphics.stanford.edu/~seander/bithacks.html */
for (acc = 0; res; res >>= 1)
{
acc += res & 1;
}
In Java
void main(String[] args){
boolean value = moreThanOneChanged("101", "001");
}
static boolean moreThanOneChanged(String input, String current){
if(input.length() != current.length()) return false;
char[] first = input.toCharArray();
char[] second = current.toCharArray();
for(int i = 0, j = 0; i < input.length(); i++){
if(first[i] == second[i])
j++;
if(j > 1)
return true;
}
return false;
}
You can prove it to yourself fairly easily by using an and comparison between an exclusive or of each value and the exclusive or minus 1. It is easier to visualize what takes place by looking at the binary representation of the values and results. Below the function onebitoff performs the test. The other functions just provide a way to output the results:
#include <stdio.h>
#include <limits.h> /* for CHAR_BIT */
#define WDSZ 64
/** returns pointer to binary representation of 'n' zero padded to 'sz'.
* returns pointer to string contianing binary representation of
* unsigned 64-bit (or less ) value zero padded to 'sz' digits.
*/
char *cpbin (unsigned long n, int sz)
{
static char s[WDSZ + 1] = {0};
char *p = s + WDSZ;
int i;
for (i=0; i<sz; i++) {
p--;
*p = (n>>i & 1) ? '1' : '0';
}
return p;
}
/* return true if one-bit bitwise variance */
int onebitoff (unsigned int a, unsigned int b)
{
return ((a ^ b) & ((a ^ b) - 1)) ? 0 : 1;
}
/* quick output of binary difference for 2 values */
void showdiff (unsigned int a, unsigned int b)
{
if (onebitoff (a, b))
printf ( " values %u, %u - vary by one-bit (bitwise)\n\n", a, b);
else
printf ( " values %u, %u - vary by other than one-bit (bitwise)\n\n", a, b);
printf (" %3u : %s\n", a, cpbin (a, sizeof (char) * CHAR_BIT));
printf (" %3u : %s\n", b, cpbin (b, sizeof (char) * CHAR_BIT));
printf (" xor : %s\n\n", cpbin ((a ^ b), sizeof (char) * CHAR_BIT));
}
int main () {
printf ("\nTest whether the following numbers vary by a single bit (bitwise)\n\n");
showdiff (1, 5);
showdiff (5, 6);
showdiff (6, 1);
showdiff (97, 105); /* just as a further test */
return 0;
}
output:
$ ./bin/bitsvary
Test whether the following numbers vary by a single bit (bitwise)
values 1, 5 - vary by one-bit (bitwise)
1 : 00000001
5 : 00000101
xor : 00000100
values 5, 6 - vary by other than one-bit (bitwise)
5 : 00000101
6 : 00000110
xor : 00000011
values 6, 1 - vary by other than one-bit (bitwise)
6 : 00000110
1 : 00000001
xor : 00000111
values 97, 105 - vary by one-bit (bitwise)
97 : 01100001
105 : 01101001
xor : 00001000

find the index of the highest bit set of a 32-bit number without loops obviously

Here's a tough one(atleast i had a hard time :P):
find the index of the highest bit set of a 32-bit number without using any loops.
With recursion:
int firstset(int bits) {
return (bits & 0x80000000) ? 31 : firstset((bits << 1) | 1) - 1;
}
Assumes [31,..,0] indexing
Returns -1 if no bits set
| 1 prevents stack overflow by capping the number of shifts until a 1 is reached (32)
Not tail recursive :)
Very interesting question, I will provide you an answer with benchmark
Solution using a loop
uint8_t highestBitIndex( uint32_t n )
{
uint8_t r = 0;
while ( n >>= 1 )
r++;
return r;
}
This help to better understand the question but is highly inefficient.
Solution using log
This approach can also be summarize by the log method
uint8_t highestSetBitIndex2(uint32_t n) {
return (uint8_t)(log(n) / log(2));
}
However it is also inefficient (even more than above one, see benchmark)
Solution using built-in instruction
uint8_t highestBitIndex3( uint32_t n )
{
return 31 - __builtin_clz(n);
}
This solution, while very efficient, suffer from the fact that it only work with specific compilers (gcc and clang will do) and on specific platforms.
NB: It is 31 and not 32 if we want the index
Solution with intrinsic
#include <x86intrin.h>
uint8_t highestSetBitIndex5(uint32_t n)
{
return _bit_scan_reverse(n); // undefined behavior if n == 0
}
This will call the bsr instruction at assembly level
Solution using inline assembly
LZCNT and BSR can be summarize in assembly with the below functions:
uint8_t highestSetBitIndex4(uint32_t n) // undefined behavior if n == 0
{
__asm__ __volatile__ (R"(
.intel_syntax noprefix
bsr eax, edi
.att_syntax noprefix
)"
);
}
uint8_t highestSetBitIndex7(uint32_t n) // undefined behavior if n == 0
{
__asm__ __volatile__ (R"(.intel_syntax noprefix
lzcnt ecx, edi
mov eax, 31
sub eax, ecx
.att_syntax noprefix
)");
}
NB: Do Not Use unless you know what you are doing
Solution using lookup table and magic number multiplication (probably the best AFAIK)
First you use the following function to clear all the bits except the highest one:
uint32_t keepHighestBit( uint32_t n )
{
n |= (n >> 1);
n |= (n >> 2);
n |= (n >> 4);
n |= (n >> 8);
n |= (n >> 16);
return n - (n >> 1);
}
Credit: The idea come from Henry S. Warren, Jr. in his book Hacker's Delight
Then we use an algorithm based on DeBruijn's Sequence to perform a kind of binary search:
uint8_t highestBitIndex8( uint32_t b )
{
static const uint32_t deBruijnMagic = 0x06EB14F9; // equivalent to 0b111(0xff ^ 3)
static const uint8_t deBruijnTable[64] = {
0, 0, 0, 1, 0, 16, 2, 0, 29, 0, 17, 0, 0, 3, 0, 22,
30, 0, 0, 20, 18, 0, 11, 0, 13, 0, 0, 4, 0, 7, 0, 23,
31, 0, 15, 0, 28, 0, 0, 21, 0, 19, 0, 10, 12, 0, 6, 0,
0, 14, 27, 0, 0, 9, 0, 5, 0, 26, 8, 0, 25, 0, 24, 0,
};
return deBruijnTable[(keepHighestBit(b) * deBruijnMagic) >> 26];
}
Another version:
void propagateBits(uint32_t *n) {
*n |= *n >> 1;
*n |= *n >> 2;
*n |= *n >> 4;
*n |= *n >> 8;
*n |= *n >> 16;
}
uint8_t highestSetBitIndex8(uint32_t b)
{
static const uint32_t Magic = (uint32_t) 0x07C4ACDD;
static const int BitTable[32] = {
0, 9, 1, 10, 13, 21, 2, 29,
11, 14, 16, 18, 22, 25, 3, 30,
8, 12, 20, 28, 15, 17, 24, 7,
19, 27, 23, 6, 26, 5, 4, 31,
};
propagateBits(&b);
return BitTable[(b * Magic) >> 27];
}
Benchmark with 100 million calls
compiling with g++ -std=c++17 highestSetBit.cpp -O3 && ./a.out
highestBitIndex1 136.8 ms (loop)
highestBitIndex2 183.8 ms (log(n) / log(2))
highestBitIndex3 10.6 ms (de Bruijn lookup Table with power of two, 64 entries)
highestBitIndex4 4.5 ms (inline assembly bsr)
highestBitIndex5 6.7 ms (intrinsic bsr)
highestBitIndex6 4.7 ms (gcc lzcnt)
highestBitIndex7 7.1 ms (inline assembly lzcnt)
highestBitIndex8 10.2 ms (de Bruijn lookup Table, 32 entries)
I would personally go for highestBitIndex8 if portability is your focus, else gcc built-in is nice.
Floor of logarithm-base-two should do the trick (though you have to special-case 0).
Floor of log base 2 of 0001 is 0 (bit with index 0 is set).
" " of 0010 is 1 (bit with index 1 is set).
" " of 0011 is 1 (bit with index 1 is set).
" " of 0100 is 2 (bit with index 2 is set).
and so on.
On an unrelated note, this is actually a pretty terrible interview question (I say this as someone who does technical interviews for potential candidates), because it really doesn't correspond to anything you do in practical programming.
Your boss isn't going to come up to you one day and say "hey, so we have a rush job for this latest feature, and it needs to be implemented without loops!"
You could do it like this (not optimised):
int index = 0;
uint32_t temp = number;
if ((temp >> 16) != 0) {
temp >>= 16;
index += 16;
}
if ((temp >> 8) != 0) {
temp >>= 8
index += 8;
}
...
sorry for bumping an old thread, but how about this
inline int ilog2(unsigned long long i) {
union { float f; int i; } = { i };
return (u.i>>23)-27;
}
...
int highest=ilog2(x); highest+=(x>>highest)-1;
// and in case you need it
int lowest = ilog2((x^x-1)+1)-1;
this can be done as a binary search, reducing complexity of O(N) (for an N-bit word) to O(log(N)). A possible implementation is:
int highest_bit_index(uint32_t value)
{
if(value == 0) return 0;
int depth = 0;
int exponent = 16;
while(exponent > 0)
{
int shifted = value >> (exponent);
if(shifted > 0)
{
depth += exponent;
if(shifted == 1) return depth + 1;
value >>= exponent;
}
exponent /= 2;
}
return depth + 1;
}
the input is a 32 bit unsigned integer.
it has a loop that can be converted into 5 levels of if-statements , therefore resulting in 32 or so if-statements. you could also use recursion to get rid of the loop, or the absolutely evil "goto" ;)
Let
n - Decimal number for which bit location to be identified
start - Indicates decimal value of ( 1 << 32 ) - 2147483648
bitLocation - Indicates bit location which is set to 1
public int highestBitSet(int n, long start, int bitLocation)
{
if (start == 0)
{
return 0;
}
if ((start & n) > 0)
{
return bitLocation;
}
else
{
return highestBitSet(n, (start >> 1), --bitLocation);
}
}
long i = 1;
long startIndex = (i << 31);
int bitLocation = 32;
int value = highestBitSet(64, startIndex, bitLocation);
System.out.println(value);
int high_bit_set(int n, int pos)
{
if(pos<0)
return -1;
else
return (0x80000000 & n)?pos:high_bit_set((n<<1),--pos);
}
main()
{
int n=0x23;
int high_pos = high_bit_set(n,31);
printf("highest index = %d",high_pos);
}
From your main call function high_bit_set(int n , int pos) with the input value n, and default 31 as the highest position. And the function is like above.
Paislee's solution is actually pretty easy to make tail-recursive, though, it's a much slower solution than the suggested floor(log2(n));
int firstset_tr(int bits, int final_dec) {
// pass in 0 for final_dec on first call, or use a helper function
if (bits & 0x80000000) {
return 31-final_dec;
} else {
return firstset_tr( ((bits << 1) | 1), final_dec+1 );
}
}
This function also works for other bit sizes, just change the check,
e.g.
if (bits & 0x80) { // for 8-bit
return 7-final_dec;
}
Note that what you are trying to do is calculate the integer log2 of an integer,
#include <stdio.h>
#include <stdlib.h>
unsigned int
Log2(unsigned long x)
{
unsigned long n = x;
int bits = sizeof(x)*8;
int step = 1; int k=0;
for( step = 1; step < bits; ) {
n |= (n >> step);
step *= 2; ++k;
}
//printf("%ld %ld\n",x, (x - (n >> 1)) );
return(x - (n >> 1));
}
Observe that you can attempt to search more than 1 bit at a time.
unsigned int
Log2_a(unsigned long x)
{
unsigned long n = x;
int bits = sizeof(x)*8;
int step = 1;
int step2 = 0;
//observe that you can move 8 bits at a time, and there is a pattern...
//if( x>1<<step2+8 ) { step2+=8;
//if( x>1<<step2+8 ) { step2+=8;
//if( x>1<<step2+8 ) { step2+=8;
//}
//}
//}
for( step2=0; x>1L<<step2+8; ) {
step2+=8;
}
//printf("step2 %d\n",step2);
for( step = 0; x>1L<<(step+step2); ) {
step+=1;
//printf("step %d\n",step+step2);
}
printf("log2(%ld) %d\n",x,step+step2);
return(step+step2);
}
This approach uses a binary search
unsigned int
Log2_b(unsigned long x)
{
unsigned long n = x;
unsigned int bits = sizeof(x)*8;
unsigned int hbit = bits-1;
unsigned int lbit = 0;
unsigned long guess = bits/2;
int found = 0;
while ( hbit-lbit>1 ) {
//printf("log2(%ld) %d<%d<%d\n",x,lbit,guess,hbit);
//when value between guess..lbit
if( (x<=(1L<<guess)) ) {
//printf("%ld < 1<<%d %ld\n",x,guess,1L<<guess);
hbit=guess;
guess=(hbit+lbit)/2;
//printf("log2(%ld) %d<%d<%d\n",x,lbit,guess,hbit);
}
//when value between hbit..guess
//else
if( (x>(1L<<guess)) ) {
//printf("%ld > 1<<%d %ld\n",x,guess,1L<<guess);
lbit=guess;
guess=(hbit+lbit)/2;
//printf("log2(%ld) %d<%d<%d\n",x,lbit,guess,hbit);
}
}
if( (x>(1L<<guess)) ) ++guess;
printf("log2(x%ld)=r%d\n",x,guess);
return(guess);
}
Another binary search method, perhaps more readable,
unsigned int
Log2_c(unsigned long x)
{
unsigned long v = x;
unsigned int bits = sizeof(x)*8;
unsigned int step = bits;
unsigned int res = 0;
for( step = bits/2; step>0; )
{
//printf("log2(%ld) v %d >> step %d = %ld\n",x,v,step,v>>step);
while ( v>>step ) {
v>>=step;
res+=step;
//printf("log2(%ld) step %d res %d v>>step %ld\n",x,step,res,v);
}
step /= 2;
}
if( (x>(1L<<res)) ) ++res;
printf("log2(x%ld)=r%ld\n",x,res);
return(res);
}
And because you will want to test these,
int main()
{
unsigned long int x = 3;
for( x=2; x<1000000000; x*=2 ) {
//printf("x %ld, x+1 %ld, log2(x+1) %d\n",x,x+1,Log2(x+1));
printf("x %ld, x+1 %ld, log2_a(x+1) %d\n",x,x+1,Log2_a(x+1));
printf("x %ld, x+1 %ld, log2_b(x+1) %d\n",x,x+1,Log2_b(x+1));
printf("x %ld, x+1 %ld, log2_c(x+1) %d\n",x,x+1,Log2_c(x+1));
}
return(0);
}
well from what I know the function Log is Implemented very efficiently in most programming languages, and even if it does contain loops , it is probably very few of them , internally
So I would say that in most cases using the log would be faster , and more direct.
you do have to check for 0 though and avoid taking the log of 0, as that would cause the program to crash.

Resources