Offline
God Member
Karma: 10
Posts: 862
|
 |
« on: March 16, 2012, 10:44:48 am » |
after trial and error (literally) of about 4 hours (I'm a pascal coder, it's hard to completely change mindset) managed to nail out a small routine that did what i need but i can't help but feel there's a much shorter version that could be written to replace this one....
String Convert(long Val) { String s = String(Val); int bc; int where = s.length()-1; String part1 = ""; String part2 = ""; for(bc=0; bc<where; bc++) part1 = part1 + s[bc]; part2 = s[where]; s = part1 + "." + part2; return(s); }
eg 168 becomes 16.8 10023 becomes 1002.3
In pascal it's simply String:=Copy(String1,1,Length(String)-1)+'.'String[Length(String)]); don't quote me, I can't be bothered to compile that line right now.
so yes, can that routine be shortened?
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 311
Posts: 35470
Seattle, WA USA
|
 |
« Reply #1 on: March 16, 2012, 10:59:23 am » |
so yes, can that routine be shortened? Yes. String s = String(Val); Wasteful. Create in instance of the String class using the value in Val. Then, invoke the copy constructor to transfer the data the the new instance of the String class called s. Then, call the String destructor to get rid on the object on the right. String s(Val); One call to the constructor. Then, you can get the length of the instance. Get the character in that last position of the object. Replace that character with the ., and append what was the last character. String s(Val); <-- s = "10023" char last = s.charAt(s.length()-1); < -- last = '3' s.setCharAt(s.length()-1, ','); <-- s = "1002." s.append(last); <-- s = "1002.3" Alternatively, you could divide Val by 10 (to get 1002) and use Val %10 (to get 3), and create 2 strings ("1002" and "3") and concatenate them with a "." between them. Even better, though, would be to ditch the String class and use a char array. Use the itoa() function to convert the value to a string. copy the last character, replace the last character with the '.', and put the last character where the NULL was, and add a new NULL on the end.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
God Member
Karma: 10
Posts: 862
|
 |
« Reply #2 on: March 16, 2012, 11:09:19 am » |
Alright calm down lol, thank you... Then again, i'd probably say the same back to you if I was using Delphi  just to show you what i mean this is what i'm used to  function InstancePropsToStr(Instance: TPersistent): String; var ms: TMemoryStream; Writer: TWriter; p: pointer; begin ms := TMemoryStream.Create; Writer := TWriter.Create(ms, 4096);
// hacking: calculate address of WriteProperties method in Delphi3,4,CBulder3,4 {$IFDEF RSL_CB4LE} p := @TWriter.WriteCollection; if PByte(p)^=$FF then begin //skip jmp table (for package) Inc(PByte(p), $2); p := Pointer(PInteger(p)^); p := Pointer(PInteger(p)^); end; {$IFDEF RSL_CB3} Inc(PByte(p), $47); {$ELSE} Inc(PByte(p), $37); {$ENDIF} if PByte(PChar(p)-1)^<>$E8 then begin Result := ''; exit; end; Inc(PByte(p), PInteger(p)^+4); if PByte(p)^<>$55 then begin Result := ''; exit; end; asm push eax push edx mov eax, writer mov edx, Instance call p pop edx pop eax end; {$ELSE} THackWriter(writer).WriteProperties(Instance); {$ENDIF}
Writer.WriteListEnd; Writer.FlushBuffer; ms.Position := 0; SetLength(Result, ms.Size); Move(ms.Memory^, PChar(Result)^, ms.Size); Writer.Free; ms.Free; end;
it's like leaning Spanish when you've known english all your life.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
God Member
Karma: 10
Posts: 862
|
 |
« Reply #3 on: March 16, 2012, 11:14:02 am » |
Well anyway ... after some more calibration, finished, this is in C, sorry to the people who get confused by C, 0 = water freezes 100c = boils at sea level, 30c is perfect. http://110.175.97.110:1234/80's already use on my machine by orb, so no naughty business lol.... but yes, i bought a barometer and thought id have go, soldered on the header pins and finally got it displaying the correct info... also the pressure is higher on the inside of the house than it is on the out, if i opened all the doors and windows to equalize the pressure would that not drop the pressure reading?... anyway 3am tired.
|
|
|
|
« Last Edit: March 16, 2012, 11:16:00 am by cjdelphi »
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 311
Posts: 35470
Seattle, WA USA
|
 |
« Reply #4 on: March 16, 2012, 11:16:57 am » |
So, what are we supposed to do with a link that is local to your network?
|
|
|
|
|
Logged
|
|
|
|
|
Gosport, UK
Offline
Faraday Member
Karma: 19
Posts: 3118
|
 |
« Reply #5 on: March 16, 2012, 12:33:23 pm » |
I probably ought to point out that a string in Pascal is the same as a string in C, a null-terminated array of chars. The Delphi String class is not standard Pascal.
|
|
|
|
|
Logged
|
|
|
|
|
West Des Moines, Iowa USA
Offline
Sr. Member
Karma: 2
Posts: 429
|
 |
« Reply #6 on: March 16, 2012, 12:36:20 pm » |
Alititude: 44330 That's right up there! For comparison, Mount Everest is only 29035 feet / 8850 m high.
|
|
|
|
|
Logged
|
There's always a better way!
|
|
|
|
Offline
God Member
Karma: 10
Posts: 862
|
 |
« Reply #7 on: March 17, 2012, 12:10:31 am » |
lol, that's what I love programming with Arduino, even with my computer off (when any of my old apps would now be 'off', the Arduino keeps on kicking via USB power) and people obviously get to see any bug i introduce in real time via a live url which dumps out my raw data.. I'll may as well continue, the problem i'm having is with a Barometer Sensor, many many MANY examples out there and all giving different results, so i'm not sure which one's working... and when it comes to the altitude/millibar reading, I simply took the reading I got eg 22000 and deducted what mr weatherman said the real pressure was, i'm actually at 180m above see level so that's my target number, the hpa, is 20 out (not bad so it's at least working) and the altitude i have no idea... http://www.bosch-sensortec.com/content/language1/downloads/BMP085_DataSheet_Rev.1.0_01July2008.pdfis what i'm working from at the moment to correct the errors in my code, math is very weak point of mine lol, I'm more used to working with utilities/string work.. my code here.. #include <Wire.h> #include <String.h> #include <NewSoftSerial.h> #include <SPI.h> #include <Ethernet.h> #include <BMP085.h> #include <utility/w5100.h>
#define ledPinB 6 #define ledPinG 5 #define ledPinR 4 #define SpeakerPin 7 #define ComputerPowerPin 8
#define I2C_ADDRESS 0x77 //77?
// The IP address will be dependent on your local network: byte mac[] = { 0x0C, 0x00, 0x0C, 0xE, 0xA, 0xB }; byte ip[] = { 192,168,1, 253 }; byte thismsg;
Server server(1234); NewSoftSerial mySerial(2, 3);
const unsigned char oversampling_setting = 3; //oversamplig for measurement const unsigned char pressure_waittime[4] = { 5, 8, 14, 26 };
//just taken from the BMP085 datasheet int ac1; int ac2; int ac3; unsigned int ac4; unsigned int ac5; unsigned int ac6; int b1; int b2; int mb; int mc; int md;
void setup() { Ethernet.begin(mac, ip); Serial.begin(9600); server.begin(); mySerial.begin(9600); pinMode(ledPinB, OUTPUT); pinMode(ledPinG, OUTPUT); pinMode(ledPinR, OUTPUT); pinMode(SpeakerPin, OUTPUT); pinMode(ComputerPowerPin, OUTPUT); Serial.begin(9600); // start serial for output Serial.println("Setting up BMP085"); Wire.begin(); bmp085_get_cal_data(); }
void loop() {
char c; int temperature; long pressure; long alti;
bmp085_read_temperature_and_pressure(&temperature,&pressure,&alti);
// temperature = temperature - 18;
Client client = server.available(); if (client) { while (client.connected()) { { // char c = client.read(); client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println(); client.println("Local IP: 192.168.1.253/WAN IP: 110.175.97.110<br>"); client.println("Hello from my Arduino!<br> Helloooo"); client.print("<br>The Temperature Is (in my bedroom that is lol): "); client.print(Convert(temperature)); client.print("c"); client.print("<br>"); client.print("<br>The Barometer Reading: "); client.print(Convert(pressure)); client.print("isobars/milibars whatever they are<br>"); client.print("<br>"); client.print("Alititude: "); client.print(alti); client.print("<br>"); client.print("<br>"); client.print("Written by Craig C in Arduino (Crude Weather Station)"); // if (c=='b') client.print(pressure,DEC); // if (c=='Q') client.stop(); delay(100); client.stop(); delay(100); // CheckChar(c); } }}
if (mySerial.available()) { c = (char)mySerial.read(); CheckChar(c); if (c=='t') mySerial.println(temperature,DEC); if (c=='b') mySerial.println(pressure,DEC); }
// Serial.print(temperature,DEC); // Serial.print(' '); // Serial.print(pressure,DEC); // Serial.println(); // delay(200); }
void CheckChar(char c) { // if (c=='B') { digitalWrite(ledPinB,HIGH); } // if (c=='b') { digitalWrite(ledPinB,LOW); }
// if (c=='G') { digitalWrite(ledPinG,HIGH);} // if (c=='g') { digitalWrite(ledPinG,LOW); }
// if (c=='R') { digitalWrite(ledPinR,HIGH);} // if (c=='r') { digitalWrite(ledPinR,LOW); }
// if (c=='X') {LightShow1(); } // if (c=='x') { LightShow2(); }
// if (c=='S') { digitalWrite(SpeakerPin,HIGH); } // if (c=='s') { digitalWrite(SpeakerPin,LOW); } if (c=='p') { digitalWrite(ComputerPowerPin,HIGH); delay(50); digitalWrite(ComputerPowerPin,LOW); } if (c=='P') { digitalWrite(ComputerPowerPin,HIGH); delay(5000); digitalWrite(ComputerPowerPin,LOW); } }
String Convert(long Val) { String s = String(Val); int bc; int where = s.length()-1; String part1 = ""; String part2 = ""; for(bc=0; bc<where; bc++) part1 = part1 + s[bc]; part2 = s[where]; s = part1 + "." + part2; return(s); }
//more to be posted as i reached max length for a quote
The bluetooth code was just a small experiment of mine to remotely switch my computer on and off (I removed the push button and wired it up to pin 8 on the Arduino and fed it to a transistor, which then has the ability to forcefully turn it off (if windows hangs) and shut it down gently, soft power off via a button press longer than 4000ms.... i use 50ms for a quick press, works wonderfully, i now use it to restart my server on my pc if it hangs or if the power goes out..... (I also had this working for internet, but figured with the simple checking of each byte it receives, not a good idea as a simple /GET request would shut down the pc if someone stumbled across the IP address and port. So anyway i'm now comparing the PDF against the code to fine tune it... I'm hoping it's the code and not some kind of fault with the unit.
|
|
|
|
« Last Edit: March 17, 2012, 12:20:19 am by cjdelphi »
|
Logged
|
|
|
|
|
Offline
God Member
Karma: 10
Posts: 862
|
 |
« Reply #8 on: March 17, 2012, 12:11:06 am » |
void bmp085_read_temperature_and_pressure(int* temperature, long* pressure, long* alti) { long tmp; long x1, x2, x3, b3, b5, b6, p, b7; unsigned long b4; long t; //calculate the temperature long up = bmp085_read_up(); long ut= bmp085_read_ut(); x1 = ((long)ut - ac6) * ac5 >> 15; x2 = ((long) mc << 11) / (x1 + md); b5 = x1 + x2; t =((b5 + 8)/2 )>> 4; *temperature = t;
//calculate the pressure b6 = b5 - 4000; x1 = (b2 * (b6 * b6 >> 12)) >> 11; x2 = ac2 * b6 >> 11; x3 = x1 + x2; b3 = (((int32_t) ac1 * 4 + x3)<<oversampling_setting + 2) >> 2; x1 = ac3 * b6 >> 13; x2 = (b1 * (b6 * b6 >> 12)) >> 16; x3 = ((x1 + x2) + 2) >> 2; b4 = (ac4 * (uint32_t) (x3 + 32768)) >> 15; b7 = ((uint32_t) up - b3) * (50000 >> oversampling_setting); p = b7 < 0x80000000 ? (b7 * 2) / b4 : (b7 / b4) * 2; x1 = (p >> 8) * (p >> 8); x1 = (x1 * 3038) >> 16; x2 = (-7357 * p) >> 16; *pressure = p + ((x1 + x2 + 3791) >> 4); *pressure = *pressure - 10750; //adjust for sea level //my own
// up = bmp085_read_up(); ut= bmp085_read_ut();
b6 = b5 - 4000; // b5 is updated by calcTrueTemperature(). x1 = (b2* (b6 * b6 >> 12)) >> 11; x2 = ac2 * b6 >> 11; x3 = x1 + x2; // tmp = ac1; // tmp = (tmp * 4 + x3) << oversampling_settings; // b3 = (tmp + 2) >> 2; b3 = (((int32_t) ac1 * 4 + x3)<<oversampling_setting + 2) >> 2; x1 = ac3 * b6 >> 13; x2 = (b1 * (b6 * b6 >> 12)) >> 16; x3 = ((x1 + x2) + 2) >> 2; b4 = (ac4 * (uint32_t) (x3 + 32768)) >> 15; // b7 = ((uint32_t)up - b3) * (50000 >> _oss); b7 = ((uint32_t) up - b3) * (50000 >> oversampling_setting); p = b7 < 0x80000000 ? (b7 << 1) / b4 : (b7 / b4) << 1; x1 = (p >> 8) * (p >> 8); x1 = (x1 * 3038) >> 16; x2 = (-7357 * p) >> 16; p = p - 10750; //my own sea level mod *pressure = p + ((x1 + x2 + 3791) >> 4);
// int _cm_Offset = 0; *alti = 443300 * (1 - pow((p / (float)10750), 0.1903)); // *alti = 44330 * (1-(p/10750)*1/5.255); //
// // *pressure = p + ((x1 + x2 + 3791) >> 4); // printf("Altitude: %ldm\n\n", altitude);*/ // run_num = run_num+1; //delay_ms(40000);
}
unsigned int bmp085_read_ut() { write_register(0xf4,0x2e); delay(5); //longer than 4.5 ms return read_int_register(0xf6); }
void bmp085_get_cal_data() { Serial.println("Reading Calibration Data"); ac1 = read_int_register(0xAA); Serial.print("AC1: "); Serial.println(ac1,DEC); ac2 = read_int_register(0xAC); Serial.print("AC2: "); Serial.println(ac2,DEC); ac3 = read_int_register(0xAE); Serial.print("AC3: "); Serial.println(ac3,DEC); ac4 = read_int_register(0xB0); Serial.print("AC4: "); Serial.println(ac4,DEC); ac5 = read_int_register(0xB2); Serial.print("AC5: "); Serial.println(ac5,DEC); ac6 = read_int_register(0xB4); Serial.print("AC6: "); Serial.println(ac6,DEC); b1 = read_int_register(0xB6); Serial.print("B1: "); Serial.println(b1,DEC); b2 = read_int_register(0xB8); Serial.print("B2: "); Serial.println(b1,DEC); mb = read_int_register(0xBA); Serial.print("MB: "); Serial.println(mb,DEC); mc = read_int_register(0xBC); Serial.print("MC: "); Serial.println(mc,DEC); md = read_int_register(0xBE); Serial.print("MD: "); Serial.println(md,DEC); }
long bmp085_read_up() { write_register(0xf4,0x34+(oversampling_setting<<6)); delay(pressure_waittime[oversampling_setting]); unsigned char msb, lsb, xlsb; Wire.beginTransmission(I2C_ADDRESS); Wire.send(0xf6); // register to read Wire.endTransmission();
Wire.requestFrom(I2C_ADDRESS, 3); // read a byte while(!Wire.available()) { // waiting } msb = Wire.receive(); while(!Wire.available()) { // waiting } lsb |= Wire.receive(); while(!Wire.available()) { // waiting } xlsb |= Wire.receive(); return (((long)msb<<16) | ((long)lsb<<8) | ((long)xlsb)) >>(8-oversampling_setting); }
void write_register(unsigned char r, unsigned char v) { Wire.beginTransmission(I2C_ADDRESS); Wire.send(r); Wire.send(v); Wire.endTransmission(); }
char read_register(unsigned char r) { unsigned char v; Wire.beginTransmission(I2C_ADDRESS); Wire.send(r); // register to read Wire.endTransmission();
Wire.requestFrom(I2C_ADDRESS, 1); // read a byte while(!Wire.available()) { // waiting } v = Wire.receive(); return v; }
int read_int_register(unsigned char r) { unsigned char msb, lsb; Wire.beginTransmission(I2C_ADDRESS); Wire.send(r); // register to read Wire.endTransmission();
Wire.requestFrom(I2C_ADDRESS, 2); // read a byte while(!Wire.available()) { // waiting } msb = Wire.receive(); while(!Wire.available()) { // waiting } lsb = Wire.receive(); return (((int)msb<<8) | ((int)lsb)); }
|
|
|
|
« Last Edit: March 17, 2012, 12:18:54 am by cjdelphi »
|
Logged
|
|
|
|
|
Global Moderator
Melbourne, Australia
Offline
Shannon Member
Karma: 218
Posts: 13896
Lua rocks!
|
 |
« Reply #9 on: March 17, 2012, 12:14:28 am » |
All those crying faces make it hard to read.
Please edit your post, select the code, and put it between [code] ... [/code] tags.
You can do that by hitting the # button above the posting area.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
God Member
Karma: 10
Posts: 862
|
 |
« Reply #10 on: March 17, 2012, 12:22:44 am » |
http://www.weatherzone.com.au/sa/adelaide/clearviewthat's how i'm calibrating it, via that info. Temperature 23.8°C rising Dew Point 9.2°C rising Feels Like 23.8°C Relative Humidity 39% Wind icon SE 12km/h steady Wind Gusts 24km/h Pressure 1019.5hPa falling Fire Danger 9.8 Rain since 9am/last hr 0.0mm / 0.0mm
|
|
|
|
|
Logged
|
|
|
|
|
Wellington, New Zealand
Offline
Sr. Member
Karma: 1
Posts: 404
|
 |
« Reply #11 on: March 17, 2012, 06:36:05 am » |
after trial and error (literally) of about 4 hours (I'm a pascal coder, it's hard to completely change mindset) managed to nail out a small routine that did what i need but i can't help but feel there's a much shorter version that could be written to replace this one.... String Convert(long Val) { String s = String(Val); int bc; int where = s.length()-1; String part1 = ""; String part2 = ""; for(bc=0; bc<where; bc++) part1 = part1 + s[bc]; part2 = s[where]; s = part1 + "." + part2; return(s); }
eg 168 becomes 16.8 10023 becomes 1002.3 In pascal it's simply String:=Copy(String1,1,Length(String)-1)+'.'String[Length(String)]); don't quote me, I can't be bothered to compile that line right now. so yes, can that routine be shortened? Why mess with String? You could just use normal non-mallocy C strings like this: char *convert(long val, char *buf, int size) { snprintf(buf, size, "%d.%d", val / 10, val - ((val / 10) * 10));
return buf; }
void loop() { char buf[10]; Serial.print(convert(238, buf, sizeof(buf))); Serial.println(" Degrees C"); }
or even easier: Serial.print(val/10); Serial.print("."); Serial.print(val - ((val/10) * 10)); Serial.println(" Degrees C");
|
|
|
|
|
Logged
|
|
|
|
|
|