Hi Guys, Joe I am not really looking for the physical layer, I sort of have that, Chris is actually very close to what I am looking for. Apologies if I haven't described the problem correctly. A friend of mine sent me this and on page 389 it shows a block diagram of what I sort of would like to implement. http://www.vislab.ucr.edu/PUBLICATIONS/pubs/Journal%20and%20Conference%20Pa= pers/before10-1-1997/Journals/1985/Thespecificationofdistributed85.pdf Chris, at this point I would like to be able to get a raw value from the sensor and let the PC end do the scaling but probably later on some sensor value conditioning may be done at the micro. I will have a look at your suggestions as that is the way I want to go. "Do you need to interpret sensor values on the MCU? If not, just pass them as raw readings to the PC and let it understand what type of sensor is plugged into each pin and convert he values appropriately=97nothing to be done in the MCU code." I would still like to have a way of getting the raw value out of the ADC in a structured manner. At the PC end a function getSensorValue(sensor1) would look up sensor 1 structure pick up the function to communicate with the module that has the particular ADC which is connected to the physical sensor and get that value. on the module side the ADC sub-module should have routines to receive the request and send the correct data. This is what I am looking some info on. the communications between PC and module I already done. I like the way you are describing the sensors in a object orientated way, time to have a better look at function pointers. I will come back with a few more questions. Thanks for the help. Luis On 11 January 2013 10:03, Christopher Head wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: RIPEMD160 > > On Fri, 11 Jan 2013 08:49:30 +0000 > Luis Moreira wrote: > > > This is what I came up with as a system and also regarding the > > analogue sensors connected to the ADC module, at the moment i have no > > code just the concept of it: > > > > - The sensor(s) are physically attached to the local ADC although > > later I may want to make them remote, but lets not complicate things > > at the moment. > > - I called the system a module, the module communicates with the PC > > via the USART using a packet system which I already have working but > > not doing much. > > - I created an adc_SubModule. > > - the module will have an 8bit "address" for the moment. > > - the Sub modules will have also an 8bit "address. > > - the logical sensor is identified by a number which at this point > > will be predefined. > > > > To start with there will not be configuration on the fly, > > configuration and initialisation of the ADC will be done at startup > > and sensors created at the startup too. > > Do you need to interpret sensor values on the MCU? If not, just pass > them as raw readings to the PC and let it understand what type of > sensor is plugged into each pin and convert he values > appropriately=97nothing to be done in the MCU code. > > If you do need to interpret sensor values on the MCU, it sounds like > you=92re probably looking for a basic object-oriented programming > paradigm, which can be done quite easily in C. Here=92s what you do: > > Divide both your data and functionality into that which: > (1) is exactly the same for all sensors, > (2) is the same for all sensors of the same type (say, model number) > but different for different types or sensor (e.g. a mapping function to > convert from ADC readings to useful human-readable units, or a string > containing the type of sensor for display), and > (3) is different for each individual sensor, but exists across all > sensor types (e.g. high and low alarm levels, string name of what the > sensor is measuring=97you will usually, but not necessarily, not have > functions here, only data), and > (4) is different for each individual sensor and may not even exist for > some sensor (e.g. calibration values). > > For stuff in category 1, this really has nothing to do with the sensors > themselves. Not talking about that further. > > For stuff in category 2, define a struct type that contains all those > things. For each variable whose value differs between types of sensors, > put a variable in the struct. For each function that needs to be > implemented differently (e.g. =93convert_adc_to_printable=94) between > sensor types, put a function pointer in the struct. It=92s probably a > good idea to include an initialization function here too. This is called > the =93class struct=94 or =93ops struct=94. In this case, you would have = just > one struct type, =93struct sensor_ops { void (*init_sensor)(struct > sensor *sensor); void (*adc_to_printable)(struct sensor *sensor, > uint16_t adc, char *string_buffer); /* more stuff */ };=94. > > For stuff in category 3, define a struct type that contains all those > things, plus a variable of type =93const struct sensor_ops *=94 (called > =93ops=94), plus a variable of type =93void *=94 (called =93private=94). = In this > case, you would have just one struct type, =93struct sensor { const > struct sensor_ops *ops; void *private; uint8_t adc_channel; /* more > stuff */ };=94. > > Now write a .c file and a .h file for each model of sensor (say, > =93thermistor.c=94 and =93thermistor.h=94). > > In the .h file for a sensor model, include a definition of the sensor=92s > private data structure which holds information specific to each sensor > (e.g. =93struct thermistor_private { uint16_t filter_data[8]; };=94). If > it doesn=92t need any such data, use an empty struct. Also include an > extern declaration of the ops structure for the sensor, e.g. =93extern > const struct sensor_ops thermistor_ops;=94. > > In the .c file for a sensor model, write a function (which should be > =93static=94=97that is, not exported from the file) for each function in > category 2; in this case, say, =93static void > thermistor_adc_to_printable(const struct sensor *sensor, uint16_t adc, > char *string_buffer) { /* implement this suitable for thermistors > */ }=94. Under these functions, define one single global instance of > struct sensor_ops, like so: =93const struct sensor_ops thermistor_ops =3D > { &thermistor_adc_to_printable, /* more stuff */ };=94. As an example, > thermistor_init might look like this, if all it needs to do is clear > the filter data, showing how the private data structure is used: > > static void thermistor_init(struct sensor *sensor) { > /* Get access to the thermistor_private for THIS SENSOR. */ > struct thermistor_private *priv =3D sensor->private; > /* Clear the filter data. */ > memset(priv->filter_data, 0, sizeof(priv->filter_data)); > } > > Finally, in some other .c file (perhaps your main file, or perhaps a > separate file dedicated just to this purpose), you need to define what > sensors are on this board. Assume that on this board there are two > thermistors on ADC channels 0 and 1, a flow sensor on channel 2, and a > pressure sensor on channel 3. You would write something like this in > your board definition .c file: > > #include "flow.h" > #include "pressure.h" > #include "thermistor.h" > > static struct thermistor_private sensor0_priv, sensor1_priv; > static struct flow_private sensor2_priv; > static struct pressure_private sensor3_priv; > > struct sensor sensors[NUM_SENSORS] =3D { > { > /* ops */ &thermistor_ops, > /* private */ &sensor0_priv, > /* adc_channel */ 0, > /* more stuff */ > }, > { > /* ops */ &thermistor_ops, > /* private */ &sensor1_priv, > /* adc_channel */ 1, > /* more stuff */ > }, > { > /* ops */ &flow_ops, > /* private */ &sensor2_priv, > /* adc_channel */ 2, > /* more stuff */ > }, > { > /* ops */ &pressure_ops, > /* private */ &sensor3_priv, > /* adc_channel */ 3, > /* more stuff */ > }, > }; > > > Finally, in your main code, to e.g. initialize all your sensors, you > just do something like this: > > for (uint8_t i =3D 0; i < NUM_SENSORS; ++i) { > sensors[i].ops->init(&sensors[i]); > } > > Or to read them and show human-readable strings on an LCD, you might do > this: > > for (uint8_t i =3D 0; i < NUM_SENSORS; ++i) { > uint16_t adc_value =3D read_adc(sensors[i].adc_channel); > char buffer[32]; > sensors[i].ops->adc_to_printable(&sensors[i], adc_value, > buffer); > print_to_lcd(buffer); > } > > Or whatever you want! > > There are some variations possible. For example, if you want to get rid > of some indirection and improve code speed at the price of a bit of > memory, instead of having a void* private you can have a union with all > the private structs in it=97now instead of having to follow the pointer, > you just put the union directly inside struct sensor; the downside is > even if a particular sensor has a really small private struct, it > contains the whole union so it will be as big as the biggest private > struct. You can also leave out any of the bits that you don=92t need in > your environment, of course, and in a Harvard environment like a PIC it > may take some thinking to figure out which bits and pieces should be in > ROM (hint: the ops structs) and which should be in RAM (hint: > probably everything else) and get the pointers between them working > right. Although you *could* in theory even split the struct sensor into > two structs, one of which lives in RAM and one in ROM. Lots of options! > > Chris > -----BEGIN PGP SIGNATURE----- > Version: GnuPG v2.0.19 (GNU/Linux) > > iEYEAREDAAYFAlDv410ACgkQXUF6hOTGP7eNZwCgiz7X4cJ+RLN47lxc46k1zxyS > nTQAoJyOmgcUlGSC8z4TiNeOqnkcAxTq > =3DmCq/ > -----END PGP SIGNATURE----- > > -- > http://www.piclist.com PIC/SX FAQ & list archive > View/change your membership options at > http://mailman.mit.edu/mailman/listinfo/piclist > -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist .