Skip to content

esp32s3 + c3 ADC#5231

Open
dimajolkin wants to merge 14 commits intotinygo-org:devfrom
dimajolkin:esp32s3-adc
Open

esp32s3 + c3 ADC#5231
dimajolkin wants to merge 14 commits intotinygo-org:devfrom
dimajolkin:esp32s3-adc

Conversation

@dimajolkin
Copy link

@dimajolkin dimajolkin commented Feb 27, 2026

Miracle!
I made two implementations! they're similar, but the details are too different to merge.
It took a lot of time to repeat the calibration.
Now it's 1:1, just like in the IDF.
Now both ADCs are showing good values.

I'm not sure about reading calibrated values ​​from the fuse on the esp32c3, since they weren't present on my chip. Although the idea is 1:1, just like in the esp32s3. If they're not present, manual calibration will work just as well.

Now you can measure the voltage)

@deadprogram
Copy link
Member

deadprogram commented Feb 28, 2026

There is a lot to digest here @dimajolkin

I do not understand all of the features that have been implemented.

Generally for the ADC implementations we have only exported these functions:

func InitADC(){}
func (a ADC) Configure(ADCConfig) {}
func (a ADC) Get() uint16 {}

That would a better starting point for the ADC implementation, IMO. Anything that we need internally we should avoid exporting.

Once we have that, we can look into the more advanced/specific features of the ESP32 for ADC and how we might want to export them.

What do you think?

@dimajolkin
Copy link
Author

dimajolkin commented Feb 28, 2026

We can simplify the calibration, but we will lose accuracy.. If it is not critical, you can delete a part, but calibration is still needed for normal data. I can do MR with simplification, but not with the same accuracy of adc) I know a lot here and it's not very easy..

var c adcC3Calibration
	c.SelfCalibrate()

The whole difficulty is in the calibration. Initially, the ADC outputs GND = ~1600 and 3.3 ~2700 without voltage.
It depends on the chip. And even if you look at the Arduino, they use calibration, but call the idf function for this.

You can delete this code and see.
Technically, you can remove the fuse reading, which will simplify the feed and make the calibration automatic, but it will definitely be determined in how 3.3 = 3.1 .. 3.0 and GNS ~ 1.5 (without any calibrations)

I repeat, I can try to make a simpler calibration)

@deadprogram
Copy link
Member

Probably it should automatically call selfCalibrate() automatically when you call Configure()? That way it is an implementation detail the user does not have to worry about.

@dimajolkin
Copy link
Author

dimajolkin commented Feb 28, 2026

Probably it should automatically call selfCalibrate() automatically when you call Configure()? That way it is an implementation detail the user does not have to worry about.

Im calling initADC in Configuration.
selfConfiguration configured a ADC on all board and need call only one time..

Now, the flow of working with ADC is no different from others, all the complexity is hidden.

sensor := machine.ADC{machine.ADC2}
sensor.Configure(machine.ADCConfig{})

I would like to create a special folder in the machine for implementing internal processes so that there are only public items in the machine. And put the private machine/internal/esp32s3 as an example

@deadprogram
Copy link
Member

I think you can just not export the functions not needed from the outside. No extra package needed. Anything that is lower case will not be exported.

Also I would put everything needed for machine_esp32c3_adc.go into that file. No need for the extra files (_fuse, _regi2c`) for things that are not needed to be exported. Just put all of that code into the one file.

Same with machine_esp32s3_adc.go.

Does this make sense?

// Read register range for EFUSE_BLK2 (SYS_DATA), derived from
// esp_efuse_utility.c: range_read_addr_blocks[EFUSE_BLK2].
// BLK2 spans EFUSE_RD_SYS_PART1_DATA0_REG .. DATA7.
efuseRdBlk2Word0 = efuseBaseC3 + 0xa0 // EFUSE_RD_SYS_PART1_DATA0_REG
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just use esp.EFUSE.GetRD_SYS_PART1_DATA0()?

// logic from esp_efuse_rtc_calib_get_init_code() for ESP32-C3:
// - 10-bit field ADC1_INIT_CODE_ATTEN3 (bit 178, len 10),
// - value is interpreted as unsigned and then +1000 is applied.
func (f *Fuse) ADC1InitCodeAtten3() (uint32, bool) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why does this need to be exported?

@dimajolkin
Copy link
Author

I think you can just not export the functions not needed from the outside. No extra package needed. Anything that is lower case will not be exported.

Also I would put everything needed for machine_esp32c3_adc.go into that file. No need for the extra files (_fuse, _regi2c`) for things that are not needed to be exported. Just put all of that code into the one file.

Same with machine_esp32s3_adc.go.

Does this make sense?

Great, I'll do it now)

@dimajolkin
Copy link
Author

@deadprogram Thanks for the review, I took a fresh look and found a couple of problematic places. I'll take it for finishing) A few embarrassing things)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants