Arduinon stringit solmussa (char)

Olen copy-paste koodaaja ja nyt tuli eteen ongelma johon en vastausta Internetistä osaa etsiä. Periaatteessa tiedän miten tuo homma pitäisi tehdä, mutta tuo kääntäjä on vahvasti erimielinen.

Kyseessä on cosm.com esimerkkikoodi jota olen lähtenyt muokkaamaan. linkki.

Tuossa siis lähetetään kolme arvoa tuonne Cosm (ex. Pachube) -palveluun. Data lähetetään ‘CosmDatastream’ datatyypissä jonka rakenne on seuraava:

CosmDatastream(sensorId1, strlen(sensorId1), DATASTREAM_FLOAT)

Esimerkkikoodin pohjalta sain tehtyä toimivan ratkaisun jokainen sensori on nimetty erikseen:

[code]
char sensorId1[11];
char sensorId2[11];
char sensorId3[11];

CosmDatastream datastreams[3] = {CosmDatastream(sensorId1, strlen(sensorId1), DATASTREAM_FLOAT),
CosmDatastream(sensorId2, strlen(sensorId2), DATASTREAM_FLOAT),
CosmDatastream(sensorId3, strlen(sensorId3), DATASTREAM_FLOAT)};[/code]

Kysymys kuuluu: Miten saan poimittua nuo sensorId:t taulukosta? Olen yrittänyt seuraavalla tavalla, mutta ei onnistu (vain oleelliset osat mukana):

[code]prog_char sensor_0[] PROGMEM = “Middle”; // Sensor names stored to PROGMEM (max 10 char)
prog_char sensor_1[] PROGMEM = “Right”;
prog_char sensor_2[] PROGMEM = “Left”;

PROGMEM const char *sensorName_table[] = // Sensor names in table
{
sensor_0,
sensor_1,
sensor_2 };
char buffer[11]; // Sensor name buffer

CosmDatastream datastreams[3] = CosmDatastream(sensorId, strlen(sensorId), DATASTREAM_FLOAT);

void CosmUpload() {

for(int x=0;x<sensors;x++) {
strcpy_P(buffer, (char*)pgm_read_word(&(sensorName_table[0])));
strcpy(sensorId, buffer);
datastreams[x].setFloat(get_temperature(sensors_address[x]));

delay(2000);

}

Serial.println(“Uploading it to Cosm”);
Serial.println(feed);
int ret = cosmclient.put(feed, APIKEY);

}[/code]

Tämä toimisi muuten, mutta ongelmana on se että kaikilla kolmella anturilla on sama nimi. Eli jotenkin tuo SensorId pitäisi saada talletettua erikseen jokaiseen datastreams[x] datatyyppiin.

Yritin myös siten että tuossa datatyypissä vaihtaisin tuon sensorIdn muotoon sensorId[], mutta se meni vielä enemmän metsään…

Nyt tosin tuli mieleen ratkaisuksi se että lähetänkin nämä kaikki mittaukset yksittäisinä erillisinä paketteina. Tämä tosin lisää hieman nettiliikennettä, mutta tuolla ongelma olisi ratkaistu.


oj

&(sensorName_table[0]);

Kokeileppa tuon nollan tilalle vaihtaa “x”…

Kiitoksia vinkistä, mutta tuo oli minun copy-paste väärästä testikoodista… Näitä yrityksiä on tullut useita.

Eli myös korjatulla koodilla testatessa tuo sensorId ottaa viimeisen stringin tuolta listalta kaikkiin lähetettäviin datastreameihin:

[code] for(int x=0;x<sensors;x++) {
strcpy(sensorId, buffer);
datastreams[x].setFloat(get_temperature(sensors_address[x]));

Serial.print("I - Read sensor value ");
//Serial.print(sensorId);
Serial.print(" ");
Serial.print(x);
Serial.print(" ");
Serial.println(datastreams[x].getFloat());
delay(2000);

}[/code]

Tuloksena on:

I - Uploading it to Cosm
{
“version”:“1.0.0”,
“datastreams” : [
{ “id” : “Left”, “current_value” : “24.50” },
{ “id” : “Left”, “current_value” : “24.50” },
{ “id” : “Left”, “current_value” : “24.25” }
]
}
F - Cosm client returned following error: -400


oj

Tuossa koodinpätkässä ei aseteta sensorin nimeä, eikä kyllä tulostetakkaan sitä. Kaiken lisäksi siitä puuttuu todella paljon koodia, joten on mahdotonta sanoa mikä on vialla. :slight_smile: Suosittelen uppaamaan koodisi jonnekkin tai vaikka pasteamaan sen pastebiniin, niin voit saada apuja.

Tuo PasteBin näyttääkin sopivan hyvin tällaiseen käyttöön. En viitsinyt pastettaa koko koodia tänne foorumille kun se jaettu viidelle eri sivulle. Sensorien nimet tosiaan asetetaan tuolla pääsivulla “OneWireTest” ja tulostus tuossa loopissa kyllä toimi ihan oikein, mutta jätin sen tuosta liitetystä koodista pois epäolennaisena.

Koko koodi on nyt nähtävillä tuolla PasteBinissä: http://pastebin.com/u/petriojk

Pääohjelma
CosmUpload

Paljonhan tuossa koodissa on muutenkin korjattavaa. Esim. Web serveri ja NTP aikasynkkaus eivät toimi yhdessä CosmUploadin kanssa. Ja muutenkin tuo pääohjelman käyttäminen ja funktioiden kutsuminen ei ole avautunut minulle. Mutta eiköhän tämä tästä vielä avaudu.


oj

Tämä:

 strcpy_P(sensorId1, (char*)pgm_read_word(&(sensorName_table[0])));

Ei luultavastikkaan tee sitä mitä oletat sen tekevän. Eikös pelkkä strcpy_P tee sen mitä haluat eli kopioi PROGMEMistä stringin?

Täytyy sanoa että en tiedä mitä tuo tekee kun kopsasin tuon litanian jostain esimerkistä. Tällä tavalla kuulemma säästää muistia. Mutta tuo kyllä tuntuisi toimivan ihan oikein kun sijoittaa tuon tekstin jokaiseen SensorId muuttujaan erikseen:

strcpy_P(sensorId1, (char*)pgm_read_word(&(sensorName_table[0]))); strcpy_P(sensorId2, (char*)pgm_read_word(&(sensorName_table[1]))); strcpy_P(sensorId3, (char*)pgm_read_word(&(sensorName_table[2])));

Haluaisin korvata tuon SensorId1…SensorId3 litanian yhdellä sijoituksella tyyliin :

strcpy_P(sensorId[x], (char*)pgm_read_word(&(sensorName_table[x])));

Tarkoituksena on että joskus kun projektin kaapelointi on valmiina niin noita lämpötila-antureita olisi 20-40 kpl ympäri taloa ja tuntuu hölmöltä koodata jokainen sensori erikseen omalle rivilleen tyyliin SensorId1…40 kun kyseessä on kuitenkin juokseva numerointi…

Tämä nyt ei vaikuta lainkaan triviaalilta ongelmalta niin ehkä luovutan tämän osuuden suhteen. Tämä ongelman juurisyy saattaa ehkä olla tuolla kirjastossa. Koodissa kun on aika paljon vielä muutakin viilattavaa johon varmaan joudun vielä kyselemään täältä apuja.


oj

Oletko harkinnut esimerkiksi Sulatetut järjestelmät kirjaa? Siinä kaiketi opetellaan arduinoa käyttämään. Kopipeistaaminen on ruman näköistä, virhealtista ja johtaa kummallisesti toimivaan ohjelmaan.

Saarnaaminen sikseen.

eli strcpy funktio kopioi ensimmäiseen pointteriin toisen pointterin merkkijonon. Tässä tapauksessa luetaan osoite sensorName_table[x] taulukosta. Tämä osoite osoittaa FLASHille, joka taas luetaan char osoitteeksi. Se mitä minä en nyt tajua, on miten tuo voi toimia.

C-kieli ja AVR nyt vain ovat täysin erilaisia. FLASHin osoiteavaruus menee päällekkäin SRAMin (rekisterit, vektorit ja muisti) kanssa. Voin olla hieman ruosteessa. nongnu.org/avr-libc/user-manual/malloc.html

Tämä asia on kuitenkin käsitelty nongnu.org/avr-libc/user-man … space.html siinä lukee isolla WRONG!

Eikö riittäisi, että printf(“sensori %d”, id); ja tuolla tavalla tekisi tuon sensorin lähetyksen? Dumppaisi tuon koko nimen tallennuksen (älä tuota esimerkkiäni kopioi)

hhmmm… nyt näyttää ihan siltä että tosiaan yrität tehdä jonkin asian niin vaikeasti että pelottaa ihan… millasia antureita käytät? jos kyseessä ei ole i2c tai spi niin miten olis ihan vaan analogRead(sensor1);

tästä on hyvä lähteä: http://arduino.cc/en/Tutorial/HomePage

edit: oot näköjään incluudannu kirjhastot… löytyyhän ne myös arduinon kansiosta? tosiaan se anturin tyyppi olis hyvä tietää…

Antureina on 1-wire DS18B20 digitaaliset anturit. Kirjastojen kanssa ei ole mitään ongelmia. Lämpötilan luku onnistuu aivan mainiosti ja sen lähettäminen nettiin myös: https://cosm.com/feeds/95098. Mutta ehkä tuo tosiaan on vähän vaikeasti tehty kun yritän sijoittaa nuo stringit tuonne ohjelmamuistiin RAM:in sijaan. Tämä tosin joka tapauksessa näyttäisi vähän siltä että ongelmana on tuo käytetty kirjasto. Pitäisi ymmärtää mitä tuolla kirjastossa tehdään siinä yhteydessä kun tuo datastream muodostetaan. Mutta ensin on selviteltävä muita asioita…