Pages: [1]   Go Down
Author Topic: Strings/Floats/Strings.  (Read 1021 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Edison Member
*
Karma: 20
Posts: 2113
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 Offline
Brattain Member
*****
Karma: 549
Posts: 46107
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
so yes, can that routine be shortened?
Yes.

Code:
      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.

Code:
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 Offline
Edison Member
*
Karma: 20
Posts: 2113
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Alright calm down lol, thank you... Then again, i'd probably say the same back to you if I was using Delphi smiley

just to show you what i mean this is what i'm used to smiley-grin

Quote
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 Offline
Edison Member
*
Karma: 20
Posts: 2113
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 Offline
Brattain Member
*****
Karma: 549
Posts: 46107
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So, what are we supposed to do with a link that is local to your network?
Logged

Gosport, UK
Offline Offline
Faraday Member
**
Karma: 19
Posts: 3114
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 Offline
Sr. Member
****
Karma: 2
Posts: 428
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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 Offline
Edison Member
*
Karma: 20
Posts: 2113
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.pdf

is 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..

Code:
#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 Offline
Edison Member
*
Karma: 20
Posts: 2113
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:

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
Offline Offline
Brattain Member
*****
Karma: 452
Posts: 18694
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 Offline
Edison Member
*
Karma: 20
Posts: 2113
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

http://www.weatherzone.com.au/sa/adelaide/clearview

that'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 Offline
Sr. Member
****
Karma: 1
Posts: 404
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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....

Code:
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:

Code:
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:

Code:
    Serial.print(val/10);
    Serial.print(".");
    Serial.print(val - ((val/10) * 10));
    Serial.println(" Degrees C");
Logged


Pages: [1]   Go Up
Jump to: