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