Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

ADC Channel

Status
Not open for further replies.

TucsonDon

Member
C:
typedef enum
{
    Array =  0x0,
    Water =  0x1,
    Pool =  0xC,
    channel_CTMU =  0x1D,
    channel_DAC =  0x1E,
    channel_FVRBuf2 =  0x1F
} adc_channel_t;
adc_channel_t channel;
I am using a for loop to cycle through the adc channels (channel++) but when I increment from water to pool it goes from 1 to 2 instead of 12. How can I increment the channels?
 
Enums are not what you think they are. Use Google and review them. They are NOT meant as aliases for arbitrary numerical values. The various states an Enum type can take on have an integer value of the order they appear in the definition unless explicitly specified as you did, but that doesn't mean the undefined gaps don't exist.

So 1 = Array, 2 = Water, 3 = Pool and so on. 1 and Array can basically be used interchangeably and mean the same thing. So:
Water = 2 = 1 + 1 = Array + 1

In your case, you explicitly specify the equivalent enumerated values:

Array = 0x0
Water = 0x1
Pool = 0xC

Have you noticed your logical misstep yet? Pool = 0xC, not 0x2. Water + 1 = 0x2. So of course it won't equal to Pool. You can't have it both ways.

This is what has happened to your enum definitions:
{Array, Water, Undefined, Undefined, Undefined, Undefined, Undefined, Undefined, Undefined, Undefined, Undefined, Undefined, Pool}

So when you go Water +1, you end up at the first undefined state, not at Pool.

What you need is an array_name[] = {0x0, 0x1, 0xC} where your for loop steps through the INDEX of the array ([0], [1], [2]) and write the value being contained in that particular array element (i.e. 0x0, 0x1, 0xC).

Then if you want to use english names, apply those names to the array indexes using #defines, constants, or enums.
Code:
unsigned ADC_Ch[] = {0x0, 0x1, 0xC}; //located in array indexes 0, 1, 2, respectively

const unsigned Array  = 0; //so you can use english names when referring to array elements
const unsigned Water = 1; //you can also use #defines similarly but this is more dangerous since they can apply when they shouldn't if you aren't careful
const unsigned Pool  = 2;

//ADC_Ch[Array] same as ADC_Ch[0]
//ADC_Ch[Water] same as ADC_Ch[1]
//ADC_Ch[Pool] same as ADC_Ch[2]

You can also use enums to refer to the array elements:

Code:
enum English_Index = {Array, Water, Pool};

English_Index  This_Index
This_Index = Array; //or Water or Pool depending on whether you want 0, 1, or 2
ADC_Ch[This_Index]; //have to work through the enum variable. Can't directly do something like ADC_Ch[Water]
 
Last edited:
dknguyen thank you for the info. I am using Microchip Code Config and this is how it generated the code but it was a good learning opportunity
 
dknguyen thank you for the info. I am using Microchip Code Config and this is how it generated the code but it was a good learning opportunity

I find it does tend to produce strange code, I usually run it separately to the program I'm writing, and then cut and paste the parts I want, editing then as I go - interestingly I've used it to create analogue routines this morning, I just wanted to read a single pin, so I took the parts I wanted and removed the unwanted enum references :D
 
dknguyen thank you for the info. I am using Microchip Code Config and this is how it generated the code but it was a good learning opportunity
Ahh!! Generic code with generic assumptions.... Never used code configurator, NEVER will!!!

You only use ENUM's when you can't remember values... Normally colours in graphical adapter and such...

Very good synopsis dknguyen..
 
Last edited:
Thanks guys. As I am inexperienced and self taught it has been a good teaching tool, not only in code syntax but in troubleshooting too as with this case.
 
Weird. apparently you can assign multiple values to the same number in an enum too.

I don't do math on enums in the same way I don't go 'false' + 1 for a boolean types to get 'true'. I don't rely on the integer properties of a enum type. I just treat it as a boolean-like type with more than two possible values and forget there's a number behind it.
 
Last edited:
I now have the adc cycling through the channels, my next question is I am using thermistor to measure the temp should I take a number of samples and average and should I through out the hi & low?
 
I now have the adc cycling through the channels, my next question is I am using thermistor to measure the temp should I take a number of samples and average and should I through out the hi & low?
You shouldn't need to reject the hi and low values unless you get occasionally get wildly erroneous readings in which case you should fix the source of the problem.

I wouldn't really worry about averaging samples. I mean, you could (either by averaging the raw thermistor readings and then linearizing them or averaging linearized outputs and then averaging them, but it's much more important to get an accurate linearization of the thermistor output.

Linearizing reach reading and then averaging it is more accurate but slower since you must do calculations for each sample. Averaging raw output means averaging readings that sit on a non-linear curve so it's not as good as accurate could be. But thermal response is also so slow and sampling rate so fast (probably) that this difference might not be noticeable.
 
I am using a 10kΩ thermistor with a 10kΩ voltage divider is there something more that I need to add? I am also only powering up the thermistor to sample and then powering down.
 
I am using a 10kΩ thermistor with a 10kΩ voltage divider is there something more that I need to add? I am also only powering up the thermistor to sample and then powering down.
Well, you can get real fancy by using bridge circuits and stuff if you wanted to. If you're powering it up and down then you'll need a method to do so (a switch transistor probably, and you might need to add stuff to compensate for the voltage drop across it when you sample).
 
That was what I was lead to believe because of not being non-linear.
 
That was what I was lead to believe because of not being non-linear.

As it's a resistor you can read it like a linear joystick, check my PIC tutorials - basically you charge/dis-charge a capacitor with it and time how long it takes - you don't need an analogue input, and you can get greater resolution.
 
That was what I was lead to believe because of not being non-linear.

Well, non-linear certainly can make things inconvenient. But it can be an advantage in a sense depending on your operating area, you can greatly improved raw sensitivity so you might be able to get away without amplification (though the ideal case would just be to have a linear sensor with a very steep slope so you always have good sensitivity in all operating regimes).

Things like RTDs and thermocouples are pretty accurate, stable, and linear but have such low sensitivities that you need amplifiers or signal conditioners so you can't really half-ass it when using them. Nowadays, you can buy signal conditioning ICs that do most of that work for you but they aren't cheap and it's still not trivial.
 
So now that I have the adc figured out I have moved to the next step of reading on one MCU and displaying on another MCU v i2c.
here is the code that was generated by MCC
C:
typedef struct
{
    size_t len;
    char *data;
}buf_t;

void i2c_readDataBlock(i2c_address_t address, uint8_t reg, void *data, size_t len)
{
    // result is little endian
    buf_t    d;
    d.data = data;
    d.len = len;

    while(!i2c_open(address)); // sit here until we get the bus..
    i2c_setDataCompleteCallback(rdBlkRegCompleteHandler,&d);
    i2c_setBuffer(&reg,1);
    i2c_setAddressNACKCallback(i2c_restartWrite,NULL); //NACK polling?
    i2c_masterWrite();
    while(I2C_BUSY == i2c_close()); // sit here until finished.
}
I am confused about the void pointer and how to assign that data to a float variable. I am reading a float from one MCU and need to assign to another variable
that I have declared on the other MCU.
 
Do you really need to use a pointer? My guess is no. Surely you know what it is you want to put into the argument?

But you probably have to cast the dereferenced pointer whenenver you want to use it so the compiler knows what type it should be treated as. I've never used void pointers myself though.
 
So now that I have the adc figured out I have moved to the next step of reading on one MCU and displaying on another MCU v i2c.
here is the code that was generated by MCC
C:
typedef struct
{
    size_t len;
    char *data;
}buf_t;

void i2c_readDataBlock(i2c_address_t address, uint8_t reg, void *data, size_t len)
{
    // result is little endian
    buf_t    d;
    d.data = data;
    d.len = len;

    while(!i2c_open(address)); // sit here until we get the bus..
    i2c_setDataCompleteCallback(rdBlkRegCompleteHandler,&d);
    i2c_setBuffer(&reg,1);
    i2c_setAddressNACKCallback(i2c_restartWrite,NULL); //NACK polling?
    i2c_masterWrite();
    while(I2C_BUSY == i2c_close()); // sit here until finished.
}
I am confused about the void pointer and how to assign that data to a float variable. I am reading a float from one MCU and need to assign to another variable
that I have declared on the other MCU.

I will definitely avoid the code configurator if it generates code like that.

Mike.
P.S. the only time I've use the CC is to assign modules to pins on chips that allow them to be moved.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top