Show Posts

Pages: 1 2 [3] 4 5 ... 14

32

Using Arduino / Project Guidance / Re: LED pocket watch with Arduino mini?

on: December 01, 2013, 04:41:04 am

diameter: 1.56 inches / 39.624 mm depth: 0.52 inches / 13.208 mm
Did you start with measurements in hundredths of an inch, and then convert to millimeters? If so, then there is no way you could get accuracy of 0.001 millimeter out of that. You'd be accurate to within maybe two tenths of a millimeter, but that's all.



33

Community / Exhibition / Gallery / Re: seconds timekeeping and time conversion

on: November 29, 2013, 12:25:57 pm

If I were doing this, I would use (x >> 10) as an approximation to (x / 1000), and then use the successive subtraction to clean up.
In my experience, division by constants is not as simple as you make out. This has a lot of detail: http://www.hackersdelight.org/divcMore.pdfHacker's Delight gives this solution for unsigned division by 1000, which, on AVR, is probably as bad as the division. AVR is rotten at shifts, and all these C shifts will suck next to the handoptimized shifts in the GCC division. unsigned divu1000(unsigned n) { unsigned q, r, t; t = (n >> 7) + (n >> 8) + (n >> 12); q = (n >> 1) + t + (n >> 15) + (t >> 11) + (t >> 14); q = q >> 9; r = n  q*1000; return q + ((r + 24) >> 10); }
Maybe the author of that code had an "avoid branching at all costs" mentality, but I don't. My method is a compromise: first approximate n/1000 as n/1024, and then clean up by using a loop for the remaining subtractions. You could also iterate the n>>10 trick, as follows: unsigned divu1000(unsigned n) { unsigned q = 0; unsigned r = n + 24; unsigned t; while (r >= 1024) { t = (r >> 10); // (r >> 10) + (r >> 16) is maybe better q += t; t += (t << 1); r = (r & 1023) + (t << 3); } return q; // if you want the remainder: // r = 24; // return r; }
or, using multiplication instead of most of the shifts, unsigned divu1000(unsigned n) { unsigned q = 0; unsigned r = n + 24; unsigned t; while (r >= 1024) { t = (r >> 10); // (r >> 10) + (r >> 16) is maybe better q += t; r = (1000 * t); } return q; // if you want the remainder: // r = 24; // return r; }



34

Community / Exhibition / Gallery / Re: seconds timekeeping and time conversion

on: November 29, 2013, 04:56:57 am

It is computing: sysTime += (millis()  prevMillis) / 1000L; But doing the division through successive subtraction. But it is also working around some subtitles subtleties of unsigned subtraction that this simplification gets wrong, and keeping track of the division remainder for next time. The assumption is that (millis()  prevMillis) / 1000L almost always is 0 or 1, and in this case subtraction is way way way faster than doing the division. Recently, I've been working on killing a lot of division. If I were doing this, I would use (x >> 10) as an approximation to (x / 1000), and then use the successive subtraction to clean up. (The >> symbol is the bit shift operator. On nonnegative integers, (x >> 10) works out exactly the same as (x / 1024).)



35

Community / Exhibition / Gallery / Re: seconds timekeeping and time conversion

on: November 27, 2013, 11:12:06 pm

Has this been tested well? (Even professionals mess up calendar stuff: google "leap year bug").
By the way, I see you have lots of divisions. I wonder how hard it would be to replace them with bit shifts and addition. 1/60 = 0x0.04444444... (abuse of notation, I know, but you get the point) 1/24 = 0x0.0AAAAAAA... (AAAAAAA!! is how I feel about the slowness of division)



36

Using Arduino / Project Guidance / Re: arduino to do something every 5 days. overcome millis() overflow??

on: November 27, 2013, 10:38:49 pm

I'm surprised nobody used this an an analogy:
Let's say you start on a road trip. At the beginning of the trip, your odometer shows 99200. At the end of the trip, the odometer shows 00700. How many miles did you drive?
Did you have trouble doing the arithmetic for that one? What trick did you use to do the arithmetic? The Arduino already knows  and uses  the same trick. You don't need to worry about overflow, as long as you stick to intervals shorter than seven weeks. Since you're only going up to five days or so, there is no problem.



37

Using Arduino / Programming Questions / Re: Unable to pad zeros on Speedometer code.

on: November 26, 2013, 05:04:19 pm

tft.setCursor(45,60); if(KMPH==0) { tft.setCursor(45,60); tft.setTextColor(ST7735_RED,ST7735_BLACK); char buffer[4]; sprintf(buffer, "%03.3d", KMPH); tft.println(buffer); } else tft.print(KMPH); What elementary mistake am I committing now? In this case, the sprintf() statement is a red herring: whenever the speed is not zero, you don't reach it. Look again at your braces.



38

Using Arduino / Programming Questions / Re: Unable to pad zeros on Speedometer code.

on: November 26, 2013, 03:31:23 am

The way I see it, the real problem here is Adafruit's documentation on how to use these displays. The documentation is hard to find, hard to use, and very incomplete. From what I gather, when people have problems with it, they tend to blame themselves rather than Limor and her crew. Once I had problems similar in spirit to yours, but with a different display. It took me quite a bit of fancy detective work to figure out how to do what I needed to do, because apparently their customer service didn't have all the information I needed, either. Perhaps from Adafruit's point of view, it just isn't costeffective to have reasonably complete documentation and knowledgeable support staff. I'm going to go out on a limb here and guess that for strings, you can use tft.print() as well as tft.println(). Just try changing this: tft.setCursor(45,60); tft.println(KMPH); to this: tft.setCursor(45,60); if (KMPH >= 0) { // for positive numbers if (KMPH < 100) tft.print("0"); if (KMPH < 10) tft.print("0"); tft.println(KMPH); } else { // for negative numbers tft.print(""); if (KMPH > 10) tft.print("0"); tft.println(KMPH); } By the way, why is KMPH a "long int"? I would think that "int" would be enough (on this platform, it goes up to 32767).



40

Community / Exhibition / Gallery / Re: Arduino generating prime numbers

on: November 25, 2013, 02:14:06 am

We used BigNumber to get around the fact that intermediate results can overflow an unsigned long long in the MillerRabin test. That test requires calculating a^{b} % n for large numbers. Using numbers that are less than 10^{16}  54 bits  the results always fit into a long long, but the intermediate products that generate the exponentials can be bigger than 2^{64}. BigNumber gets around the restriction, but at some cost in speed and storage.
This code uses function "mulmodll()," that produces the product of two unsigned long long's, modulo a third unsigned long long, without overflowing on intermediate products. It generates the product internally as two unsigned long long's, and calculates the modulo by repeated shifts and mods. It has its own overhead  it has to take <something> % <something else> as many as seven times. But, it's working in native number formats, rather than in BCD, and it goes faster.
This code depends heavily on the fact that numbers bigger than 10^{16} aren't investigated. That fact simplifies the 128bit multiplication, in that certain intermediate results can't overflow, and it simplifies the mod operations, too. The code isn't general. It's assumptions are that the lower half of any argument times the upper half of any argument will be less than 2^{63}, and that the modulus will always be less than 2^{56}. With 10^{16} = 2^{53.15}, the problem fits, with a bit or two to spare.
If you are going to take many numbers modulo the same, uh, modulus, and within the limitations you describe, then we can optimize thus: Let's call our modulus "m". We operate under the assumption that m < MAX/512, where MAX is the biggest number our datatype can hold. If m is bigger than MAX/512, our intermediate results are likely to overflow, and we can't have that. In the situation described in the quote above, it appears we are safe, as MAX = (2**64)1 > 10**19, and m is at most 10**16. Let's continue with this. As in this case our MAX is (2**64)1, we make a table of 2**64 mod m, 2**72 mod m, 2**80 mod m, etc. To prevent overflows, we will also want the value of 2**63 mod m. To find the value of ((2**64)*hi + lo) mod m, with hi < 2**64 and lo < 2**64, we use this algorithm: split hi into bytes hib[0] (the lowest byte), through hib[7] (the highest byte) let r = lo mod m let r = r + (hib[0] * (2**64 mod m)) if (r >= 2**63) { let r = r  2**63 (a bit mask will work here) let r = r + (2**63 mod m) } let r = r + (hib[1] * (2**72 mod m)) if (r >= 2**63) { let r = r  2**63 (a bit mask will work here) let r = r + (2**63 mod m) } let r = r + (hib[2] * (2**80 mod m)) if (r >= 2**63) { let r = r  2**63 (a bit mask will work here) let r = r + (2**63 mod m) } ... until we've gone through all the bytes of hi ... and finally, let result = r mod m
This kills most of the modulo operations. Of course, it's untested, but I don't see why it wouldn't work.



41

Community / Exhibition / Gallery / Re: Arduino generating prime numbers

on: November 25, 2013, 01:17:49 am

I think I managed to clean up your print routine a little. WARNING: untested code!void printll(uint64_t n) { // print an unsigned long long char figs[21]; unsigned long exa = 0, giga = 0, ones = 0; ones = n; if (n >= 1000000000) { n /= 1000000000; giga = n; ones = 1000000000 * giga; if (n >= 1000000000) { exa = n / 1000000000; giga = 1000000000 * exa; } } if (exa) sprintf(figs, "%d%09d%09d", exa, giga, ones); else if (giga) sprintf(figs, "%d%09d", giga, ones); else sprintf(figs, "%d", ones); Serial.print(figs); }



42

Community / Exhibition / Gallery / Re: Billie's Hydroponic Controller

on: November 24, 2013, 10:57:31 pm

I found this in the source code: void fotoLoop() { lightADCReading = analogRead(lightSensor); // Calculating the voltage of the ADC for light lightInputVoltage = 5.0 * ((double)lightADCReading / 1024.0); // Calculating the resistance of the photoresistor in the voltage divider lightResistance = (10.0 * 5.0) / lightInputVoltage  10.0; // Calculating the intensity of light in lux currentLightInLux = 255.84 * pow(lightResistance, 10/9); }
What is that 10/9 near the bottom?



43

Community / Exhibition / Gallery / Re: Billie's Hydroponic Controller

on: November 24, 2013, 03:38:34 pm

As for the NaNs for pH: I think it is because you might have a problem writing / reading float values. I believe in killing floatingpoint arithmetic whenever practical. It is usually not difficult to find ways to avoid it. // This is evil: float pH = 0.0178 * sensorValue  1.889;
// Instead, use: int pH = (2 * sensorvalue)  ((11 * sensorValue + 9445) / 50); // This gives you 100 times the real pH, // so if the real pH is 5, the pH variable will be 500, // and if the real pH is 5.25, the pH variable will be 525, etc. // Just insert a decimal point (or decimal comma!) for display.



44

Using Arduino / Programming Questions / Re: Incorrect calculation for micros() for CPUs running at 20 MHz, 24 MHz etc.

on: November 14, 2013, 01:22:53 pm

baggage
Maybe time for a fork. No, definitely time for a fork. new data types or interfaces
I would use assembly language for this. (Correct me if I'm wrong, but I don't think there's any rule against assembly language.) 128 clock ticks every 128 clocks? So make it some higher number of clock ticks, I don't care. That doesn't mean that the principle isn't sound. And this way, you don't have to muck about with fractions; and since you're using multipleprecision (i.e. more than 8 bits) arithmetic anyway, you might as well go all the way.



45

Using Arduino / Programming Questions / Re: splitting decimal number to 2 pieces

on: November 13, 2013, 04:44:25 pm

You don't need floats at all. If you declare temp2 as an int, you can use: // the math here is that 500/1024 equals 125/256 temp2=(temp*125)/256; // temp2 is now in tenths of a degree only that will overflow so instead use: // the math here is: // 500/1024 = 125/256 = 128/256  3/256 = 1/2  3/256 temp2=(temp/2)((3*temp)/256); // temp2 is now in tenths of a degree Since you have the temperature in tenths of a degree, all you need to do is insert a decimal point.



