I am trying to take a number between 100,000 and 10,000, and push each individual number into a queue.
I use a modulus function to do this. However, I am running into issues with the Uno's 16 bit ints, which a cap at 32,767. I have tried using long ints, unsigned ints, and unsigned long ints, but the program still only pushes 0s onto the queue after 32,767. Should I try a char/string approach, or am I missing a solution?
void fill_que(unsigned int b) {
int price = b;
while(price > 0) {
queue.push(price%10);
Serial.print(price%10);
price/=10;
}
}
int main() {
unsigned int price1 = 36111;
fill_que(price1);
}
I will make a guess and say, you forgot to change the type of the variable price.
It should be:
void fill_que(unsigned long b)
{
unsigned long price = b;
while(price > 0)
{
queue.push(price%10);
Serial.print(price%10);
price/=10;
}
}
int main()
{
unsigned long price1 = 36111;
fill_que(price1);
}
Related
I am working on a project for a client so I am given a lot of code I cannot modify. I am stuff in a weird situation because of this problem. Nonetheless, I have a char with 34 indexes that I need to convert into an unsigned long type. I have seen numerous methods to accomplish this such as strtout, atol, etc. None have worked because the string starts with "0b" (ie "0b10000010000010000010000010000000"). Without the "0b", the rest of the code will not function properly. I tested with varying beginning 2 chars but nothing has led to a successful trial. Is there a function or code available that can convert the previously mentioned string into unsigned long? Any help is greatly appreciated.
You can combine the fact that a character - '0' is the number of that digit and use bit shifting to build the number up from the string:
unsigned long binaryToUL(String numberString){
int i;
unsigned long answer = 0;
if(numberString.startsWith("0b"))
for(i = 2; i<numberString.length(); i++)
answer = (answer << 1) + (numberString[i] - '0');
return answer;
}
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
unsigned long test;
String testString = "0b10000010000010000010000010000000";
test = binaryToUL(testString);
Serial.println(testString);
Serial.println(test,BIN);
Serial.println(test);
while(true)
;
}
To convert a string a string representation of a binary that started with a "0b" or "0B", you need to remove the header first, then convert to the an unsigned long (uint32_t). Depend on what is the original string type (char[], char*) but an Arduino String in this case would make it easier to work with.
String myStr = "0b10000010000010000010000010000000";
void setup(){
Serial.begin(115200);
myStr.toUpperCase();
myStr.replace("0B", "");
uint32_t ul = strtoul(myStr.c_str(), NULL, 2);
Serial.println(ul, BIN);
}
void loop(){
}
I am working on a piece of code that calls a function and passes a number < 2 ** 16. The function only returns the number * 1000:
#pragma GCC optimize("Os")
unsigned long getVal(unsigned short val) {
return val * 1000 ;
}
void setup() {
Serial.begin(9600) ;
}
void loop() {
Serial.println(getVal(200)) ;
}
Now, if I send 200 to getVal(), I should get 200000, but it returns 3392! But if I modify the function like this:
unsigned long getVal(unsigned short val) {
return val * 1000000 ;
}
I get 200000000 back, which is expected.
I can't literally multiply numbers with 1000, but 100,000 works just fine.
I already tried disabling the Optimization with O0, which doesn't fix the problem either.
I am not getting what's going on. I am on Arduino Nano.
val * 1000000 performs a long multiplication, because one of the terms (1000000) is a long
val * 1000 does an int multiplication, because both terms are int. Arduino Nano int is 16 bit wide only, so the result is truncated before it is turned into the desired long return value.
unsigned long getVal(unsigned short val) {
return val * 1000UL ;
}
is what you are looking for.
This program is a simple program designed to plot at the same time both your & Uc on the serial monitor. Arduino runs through the first for loop & plot the F1 function and after that does the same with F2. My objective is to plot them both at the same time.
My idea is to actually take a small fraction of time, let's say 10 ms, to plot F1 & the next 10 ms to plot F2, but I don't know how to write this down. I think the millis function is the solution, but I'm not quite sure how to implement it.
const short int R = 5000;
const float C = 0.0005;
const float TE = 0.1;
const float Tau = R*C;
const short int E = 5;
float t, Tinit,Tfin;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
//F1
for ( t = 0; t <= 20; t = t+TE)
{
float Ur = E*exp(-t/Tau);
Serial.println (Ur);
}
//F2
for ( t = 0; t <= 20; t = t+TE)
{
float Uc = E*(1-exp(-t/Tau));
Serial.println (Uc);
}
}
Thread can be used to solve your problem . It has a huge documentation , it is widely used library for Arduino(unofficial).
Give it a try.
It will be easy for you, if you see these :
Example - 1 (thread instance example)
Example - 2 (callback example)
Example - 3 (It is still buggy , but I think it will help)
If you want to do it without libraries , then you need to create two functions , without those loops . Like
void f1()
{
float Ur = E*exp(-t/Tau);
Serial.println (Ur);
}
void f2()
{
float Uc = E*(1-exp(-t/Tau));
Serial.println (Uc);
}
Now inside "void loop()" you can implement the basic logic of threading , which will be pretty rough , but fulfill your requirements. Like :
void loop() {
unsigned long now = millis();
static unsigned long last_finger_update;
if (now - last_finger_update >= FINGER_UPDATE_PERIOD) {
last_finger_update = now;
f1();
}
static unsigned long last_wrist_update;
if (now - last_wrist_update >= WRIST_UPDATE_PERIOD) {
last_wrist_update = now;
f2();
}
}
You have to declare two variables
const unsigned long FINGER_UPDATE_PERIOD = 1000;
const unsigned long WRIST_UPDATE_PERIOD = 1000;
All time units are in milliseconds. This strategy is collected from internet.
The most deterministic way of handling this is simply:
for (t = 0; t <= 20; t = t + TE) {
float Ur = E*exp(-t/Tau);
float Uc = E*(1-exp(-t/Tau));
Serial.println (Ur);
Serial.println (Uc);
}
More generally, you can implement a primitive resource scheduler:
while (true) {
task_one();
task_two();
}
You can do that Easily if you run RTOS in MCU as you know other solutions will also be sequential...
I've been using TridentTD_EasyFreeRTOS library it has easy way of having multiple tasks and controlling them in different sketch files..
I have a function that takes an uint64_t variable. Normally I would do this:
irsend.sendNEC(result.value);
result.value is an uint64_t as hexadecimal (I think). If I do this:
String((uint32_t) results.value, HEX)
I get this:
FF02FD
If I do:
irsend.sendNEC(0x00FF02FD)
it works perfectly and is what I want.
Instead of grabbing the result.value, I want to write it as a string (because that's what I get from the GET request). How do I make "FF02FD" into 0x00FF02FD?
EDIT:
Maybe this makes it easier to understand:
GET: http://192.168.1.125/code=FF02FD
//Arduino grabs the FF02FD by doing:
for (int i = 0; i < server.args(); i++) {
if (server.argName(i) == "code") {
String code = server.arg(i);
irsend.sendNEC(code);
}
}
This is where I get the error:
no matching function for call to 'IRsend::sendNEC(String&)'
because:
void sendNEC(uint64_t data, uint16_t nbits = NEC_BITS, uint16_t repeat = 0);
Comment writeup:
As already suggested, a string containing a hexadecimal value can be converted to an actual integer value using the C standard library functions such as "string to unsigned long" (strtoul) or "string to unsigned long long" (strtoull). From Arduino-type String one can get the actual const char* to the data using the c_str() member function. All in all, one does a hex-string to integer conversion as
uint64_t StrToHex(const char* str)
{
return (uint64_t) strtoull(str, 0, 16);
}
Which can then in code be called as
for (int i = 0; i < server.args(); i++) {
if (server.argName(i) == "code") {
String code = server.arg(i);
irsend.sendNEC(StrToHex(code.c_str()));
}
}
Appendum: Be carefull about using int or long on different platforms. On a Arduino Uno/Nano with a 8-bit microcontroller, such as the ATMega328P, an int is a int16_t. On the 32-bit ESP8266 CPU, an int is int32_t.
so i know the bases of programming, i have a decent amount of experience with java, but im learning C for school right now. I still dont completely understand the whole pointer aspect, which is what im sure caused the fault. This program works fine when run on my computer, but when i try and run it on my schools unix shell it gives me a seg fault. if someone could please explain to me why or how ive misused hte pointers, that would help me greatly.
//Matthew Gerton
//CS 222 - 002
//10/10/14
//HW Six
//libraries
#include<stdio.h>
#include<string.h>
#define max_Length 256
//prototypes
void decode(char *a, char *b);
void trimWhite(char *a);
void encode(char *a, char *b);
int main(void)
{
//character arrays
char coded[max_Length], decoded[max_Length];
//decode the sample phrase
char sample[] = {'P','H','H','W','D','W','C','R','R','F','D','Q','F','H','O','H','G','J',
'R','W','R','P','H','W','U','R','K','R','W','H','O','U','R','R','P','I','R','X','U'};
decode(sample, decoded);
//scans a user input string to decode, and decodes it
printf("\nPlease enter a phrase to decode: ");
gets(coded);
trimWhite(coded);
decode(coded, decoded);
//scans a user input phrase to encode
printf("\nPlease enter a phrase to encode: ");
gets(coded);
trimWhite(coded);
encode(coded, decoded);
}
//removes any spaces from the input
void trimWhite(char *a)
{
char temp[max_Length];
int z=0, y=0;
while(a[z]!='\0')
{
if(a[z]!=' ')
{
temp[y]=a[z];
y++;
}
z++;
}
temp[y] = '\0';
strcpy(a,temp);
}
//decodes any phrase
void decode(char *a, char *b)
{
int i=0,n;
memset(b, '\0', sizeof(b));
while(a[i]!='\0')
{
n=(int)a[i];
if(n<97)
n=n+32;
if(n<=99)
n=n+23;
else
n = n-3;
b[i]= (char) n;
i++;
}
b[i]='\0';
printf("Coded message: %s\n", a);
printf("Decoded message: %s\n", b);
}
//codes an input phrase
void encode(char *a, char *b)
{
int i=0,n;
memset(b, '\0', sizeof(b));
strcpy(b,a);
while(a[i]!='\0')
{
n=(int)a[i];
if(n<97)
a[i] = (char)(n+32);
if((n>120)
a[i] = (char)(n-23);
else
a[i] = (char)((n+3);
i++;
}
printf("Coded message: %s\n", a);
}
Your main problem is here:
char sample[] = {'P','H','H', /* snip */ ,'R','X','U'};
The sample[] array is not zero-terminated which may cause the decode() function to copy many more characters than intended, thus overwriting other variables. You need to explicitly add a terminating zero when using an initializer-list:
char sample[] = {'P','H','H', /* ... */ ,'R','X','U',0};
Or you can initialize the array using a string literal, which does include a terminating zero:
char sample[] = "PHHWDWCRRFDQFHOHGJRWRPHWURKRWHOURRPIRXU";
You should probably read "Why is the gets function dangerous".
...
void decode(char *a, char *b)
{
int i=0,n;
memset(b, '\0', sizeof(b));
Also note that the size of the array is lost when it is passed to a function. The function only receives a pointer to its first element. The memset() call above will only zero sizeof(char*) bytes (usually 4 or 8). This doesn't matter though because, as far as I can tell, you only need to zero the first byte. You could simply write:
b[0] = 0;