-
Notifications
You must be signed in to change notification settings - Fork 7.6k
millis() depends on actual cpu freq #1289
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Time is based on ticks. The code has been compiled with each tick being 240MHz (4.2ns). If you change the length of a tick (the CPU frequency), you are responsible for redefining the conversion to real time. If you use a library compiled at 80MHz ticks, you will get the right time. |
Yep, I thought that less ticks are the route of the problem. |
you can try |
@HosszuDaniel here is a test sketch I wrote that uses interrupts and timers to read A HX711, it is clock independent, see if it works for you. hw_timer_t * timer = NULL;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
volatile int nextSampleClock=25; // Default channel A 128 Gain
volatile int currentSampleClock=0; // >0 if sample in progress
volatile int sample=0;
volatile int sampleWidth = 0;
#define PD_SCK 17 // pin for sck
#define DOUT 18 // data pin
void IRAM_ATTR onSampleReady(){
portENTER_CRITICAL_ISR(&timerMux);
currentSampleClock = nextSampleClock * 2; // highs and lows
timerAlarmEnable(timer);
sample = 0;
sampleWidth = 24;
detachInterrupt(digitalPinToInterrupt(DOUT)); // shutoff trigger interrupt
portEXIT_CRITICAL_ISR(&timerMux);
}
void IRAM_ATTR onTimer() {
portENTER_CRITICAL_ISR(&timerMux);
if(currentSampleClock > 0){ // Sampling in progress
if((currentSampleClock & 1)==0){ // Set clock High
digitalWrite(PD_SCK,HIGH);
}
else { // else take reading, set clock low
if(sampleWidth>0){ // ignore the next sample selection clock cycles
sample = sample << 1;
sample = sample | digitalRead(DOUT);
sampleWidth--;
}
digitalWrite(PD_SCK,LOW);
}
currentSampleClock--;
}
else { //sample done
timerAlarmDisable(timer);
}
portEXIT_CRITICAL_ISR(&timerMux);
}
void initHX711(){
pinMode(DOUT, INPUT_PULLUP);
digitalWrite(PD_SCK, LOW);
pinMode(PD_SCK, OUTPUT);
timer = timerBegin(0, 80, true);
timerAttachInterrupt(timer, &onTimer, true);
timerAlarmWrite(timer, 1000000, true); // every 1 us
timerAlarmDisable(timer);
}
void startConversionHX711(int sampleConfig){
bool ready=false;
while(!ready){ // allow last conversion to complete
yield(); // don't want to starve the watchdog
portENTER_CRITICAL(&timerMux);
ready = currentSampleClock ==0;
portEXIT_CRITICAL(&timerMux);
}
if((sampleConfig <25)||(sampleConfig>27)) nextSampleClock = 25;
else nextSampleClock = sampleConfig;
if(digitalRead(DOUT)){// pin is high, attach int, wait for ready
currentSampleClock = 1; // mark as sample in progress
attachInterrupt(digitalPinToInterrupt(DOUT), onSampleReady, FALLING);
}
else { // already ready, no need for interrupt, just start sampling
onSampleReady();
}
}
bool sampleReadyHX711(){
bool ready;
portENTER_CRITICAL(&timerMux);
ready = currentSampleClock ==0;
portEXIT_CRITICAL(&timerMux);
return ready;
}
int sampleHX711(int sampleConfig){
startConversionHX711(sampleConfig);
while(!sampleReadyHX711()){ // wait for sample to complete
yield();
}
return sample;
}
bool readSampleHX711(int &outSample){
if(sampleReadyHX711()) {
outSample = sample;
return true;
}
else {
outSample = -1;
return false;
}
}
void setup() {
Serial.begin(115200);
initHX711();
startConversionHX711(25); // channel a, 128 gain
}
static uint32_t tick=0;
static uint32_t loopCount =0;
void loop() {
loopCount++;
int reading;
if (readSampleHX711(reading)) {
uint32_t time=millis();
Serial.printf("Current HX711 Reading %d, took %ums, looped=%d times\n",reading,time-tick,loopCount);
startConversionHX711(25);
tick=millis();
loopCount=0;
}
} You should not build code that relies on jiggering processor speed, or looping delays. Chuck. |
@stickbreaker Thanks for your code, it looks very interesting! Sadly it doesn't work for me. Only change I did to the code was to use pin 21 for data and pin 18 for clock. I would have to re-solder the pins to match your code. From what I can tell readSampleHX711 never returns true, so no sample is retrieved. Can this be related to the pins I used? Also, if someone is interested, I added the output of my logic analyzer for the bodge/HX711 library here: bogde/HX711#75 |
Hardware:
Board: ?Adafruit ESP32 Feather Clone?
Core Installation/update date: ?15/march/2018?
IDE name: ?Arduino IDE?
Flash Frequency: ?80Mhz?
Upload Speed: ?921600?
Description:
If I change the CPU freq then the output of millis() becomes invalid, it changes inversely proportionally with the freq. Perhaps it is a known error but I haven't see any documentation about it.
#include "soc/rtc.h"
void setup() {
rtc_clk_cpu_freq_set(RTC_CPU_FREQ_80M);
int startTime, interval;
}
void loop() {
startTime = millis();
delay(1000);
interval = millis() - startTime; // it will be 1000, but that is 3000 in real
}
The text was updated successfully, but these errors were encountered: