PDA

View Full Version : Is there a wise way to debug a large code?



CuriousOne
- 29th June 2021, 21:39
Hello.
My deluxe nixie clock V2.0 project is almost complete, PCBs assembled and tested, enclosures made and software written, however, I'm trying to debug a nasty bug with no success. The issue is as follows, I have option for auto brightness, which gradually decreases brightness starting at 18:00, till 23:00 then keeps at low level till 06:00 and gradually increases it till 10:00. This is done via this subroutine:



DIMMER: 'auto dim routine
IF Z2=06 THEN HPWM 2,150,2000
IF Z2=08 THEN HPWM 2,200,2000
IF Z2=10 THEN HPWM 2,255,2000
IF Z2=18 THEN HPWM 2,200,2000
IF Z2=19 THEN HPWM 2,150,2000
IF Z2=20 THEN HPWM 2,100,2000
IF Z2=21 THEN HPWM 2,20,2000
IF Z2=23 THEN HPWM 2,10,2000
return


Z2 is decoded from RTC reading (DS3231) and converted to DEC with this:


Z2=(RTCHour >> 4)*10+RTCHour // 16 'decode hours


But there is a strange problem. After time reaches 18:00, in each minute, clock enters setup mode! I exit setup mode, it works fine, but when minute changes, instead of doing display refresh, as it is defined in software, it goes into setup again. This happens all night long, but during the daytime, after 10 o'clock, it works all fine!

Setup mode is called via pressing a button, which is connected to ADC:


if ticker>150 and ard<100 then ticker=1: goto premakro (ticker is delay loop counter for de-bouncing and ARD is ADC input)


So what I have done:

Checked Z2 variable, it is "exclusive" and only used in these two code samples posted above.
"premakro" subroutine is being called from only one place in the code and there are no other entries referring to it.

Any ideas?
I can post complete code, but it is over 700 lines long, so I guess no one will bother reading it...

CuriousOne
- 29th June 2021, 21:41
Forgot to mention, IC is 16F887A and compiler gives no errors, except warning "crossing page boundaries, ensure bits are set".
Compiled code is about 7k.

Jerson
- 30th June 2021, 03:21
If you want goto premakro to run when ticker>=150, perhaps you need to reframe that part with the else....endif

I wouldn't mind looking over the code if you want.

CuriousOne
- 30th June 2021, 07:16
"premakro" works fine, when I press a button, it gets called.
The issue as I see, that somehow, HPWM statement, when duty cycle is less than 100%, disrupts the code.
I'm using hardware PWM generators at PORTC.1 for brightness control PWM, and PORTC.2 for alarm buzzer sound

CuriousOne
- 30th June 2021, 07:19
I modified DIMMER subroutine and set it to always make 255 duty cycle - then nothing fails. So how to relate these things together?

HenrikOlsson
- 30th June 2021, 19:35
How often is dimmer called? Every hour, every minute, every time thru the main loop?
What if you make it always outout a dutycycle of 200, which is what it's getting set to 18.00 when the problem starts? Perhaps you have a hardware issue?

Also, as a test try to get rid of the "one-liners" and do:

IF Z2=06 THEN
HPWM 2,150,2000
ENDIF

IF Z2=08 THEN
HPWM 2,200,2000
ENDIF

/Henrik.

CuriousOne
- 30th June 2021, 22:41
DIMMER gets called every second. I can fix this, but issue happens each minute, not second.
I tried inserting HPWM 1,200,2000 at random places in main loop - no issues. They only happen when that DIMMER sub is being called.
For the one-liners, they're great way to save yourself from a lot of scrolling, I'm writing code in that way for last 40 years, so I don't think that now is the time to change.
For the hardware issue, ADC reading is done at PORTA.0 and PWM output is at PORTC.1, so I don't think this can be a RMW issue.

The main loop can be divided into the following sections:

1. Get current time (read RTC)
2. If oldminute<>currentminute, then go seganime (animate all segments at each 1 minute change)
3. Convert hours into Z2
4. If autodim is enabled, then goto dimmer
5. alarm check and call subroutine
6. 12/24 hour check and conversion subroutine
7. Display current time routine
8. Keyboard handling code (ADC reading and debouncing)
9. middle dot blinking

HenrikOlsson
- 1st July 2021, 07:53
4. If autodim is enabled, then goto dimmer
GOTO?


For the one-liners, they're great way to save yourself from a lot of scrolling, I'm writing code in that way for last 40 years, so I don't think that now is the time to change.
OK but I thought we've showed by now that PBP is not "the same" as interpreted BASIC on you ZX Spectrum from '82.If you're sure that your one-liners work then fine but you wanted suggestion on how to debug the code and I was trying to give you ideas on what to try but never mind.

richard
- 1st July 2021, 08:54
Forgot to mention, IC is 16F887A

i got lost at this point


THEN HPWM 2,150,2000 ?? 16F887A does not exist 16F887 has 1 ccp module

then today


I tried inserting HPWM 1,200,2000 at random places in main loop


mind boggles

mpgmike
- 1st July 2021, 13:22
Not that this would fix your issue, but you have:


DIMMER: 'auto dim routine
IF Z2=06 THEN HPWM 2,150,2000
IF Z2=08 THEN HPWM 2,200,2000
IF Z2=10 THEN HPWM 2,255,2000
In this case I would have used:


Dimmer:
IF Z2 = 06 THEN
HPWM 2,150,2000
ELSEIF Z2 = 08 THEN...

What happens if Z2 = 07? Maybe use:


IF Z2 <= 06 THEN
HPWM 2,150,2000
ELSEIF Z2 <= 08 THEN...

CuriousOne
- 1st July 2021, 19:59
Well, there is no GOTO there is GOSUB, this was just a literal description of how it works.

16F887 has two PWM modules, which can be output at 4 different channels, read the datasheet. You can adjust duty cycle individually, just frequency will be the same.

From datasheet: - 10-bit PWM with 1, 2 or 4 output channels, programmable “dead time”, max. frequency 20 kHz.


IF Z2=07 then nothing should happen and nothing happens :)

For the cleanliness of experiment, I've built a completely new PCB today, and will check code for it at weekend.

richard
- 2nd July 2021, 00:57
16F887 has two PWM modules
apologies so it does

CuriousOne
- 4th July 2021, 19:43
Well, the different build has no such issue, but while using same code, it also uses different pinout (ADC input is PORTE.2 instead of PORTA.0), so in next days I will try to check existing build for issues.

CuriousOne
- 21st August 2021, 18:30
It is very interesting, as I unpacked the original board and put it on the table, it no longer had that issue.
And after I packed the new board into small enclosure, it started to have exactly the same issue!
I added some checks to code and here is what I've found.
I'm using ADC to get the input from the keys.
ADC IN is tied to VDD via +10K resistor, and there are two buttons, one pulls that IN to GND, another also pulls to GND, but via another 10K resistor.
So when no button is pressed, ADC input reads 255. When 1st button is pressed - it is 0, and when 2nd button is pressed, it is about 127. (My code checks it to be above 100 and below 140)

So, what happens? When I have PWM with duty cycle less than 170 (assuming HPWM 1,170,2000), the ADC input sporadically starts to read as 127, instead of 255! The lower PWM duty cycle is, often that happens.
But this only happens when there are some wires connected to ADC input (even short ones, about 10cm). So I guess, this is an hardware issue, and adding 0.1uf capacitor to ADC IN should help?

Ioannis
- 21st August 2021, 21:10
Obviously this is an EMI problem. Somewhere your circuits acts like a transmitter (PWM sharp signals are what it needs to do so).

Maybe a wrong trace, maybe a cable that is in different place, who knows?

Can you post pictures of both PCB sides and cabling? Sure big caps will help. Better find the source of the problem.

Ioannis

CuriousOne
- 21st August 2021, 22:05
Yes I can post, but the issue is that in both cases PCBs are different - it is thru hole (and big) components in one case, and small and SMD components in another, but giving the same issue. I think, maybe this is RMW issue somehow? because say PORTA.1 is used as ADC IN, but PORTA.2 is used as a digital output, has MPSA42 transistor connected to it's pin.

richard
- 22nd August 2021, 05:03
I think, maybe this is RMW issue somehow?

not at all likely , which pin is having its expected digitally "read back" value changed by a digital write to another pin on the the same port ?

as ioannis suggests this is looks very much an EMI problem that could most likely could be ameliorated by having the switch circuitry of more suitable impedance and using appropriate adc conversion speed along with sample hold time and rate.


with no schematic or code to look at it might just be bad code who would know

CuriousOne
- 22nd August 2021, 06:36
Ok, here is the part of code which reads the keys:


adcin 7,ard
if ard<130 then 'if any button is pressed
ticker=ticker+1 'increase value and wait - debouncing
pause 1
endif
if ticker>150 and ard<100 then 'if left button is pressed then next menu item
menuitem=menuitem+1
ticker=0 'reset debouncer
endif
if ticker>150 and ard<130 AND ARD>100 then 'if right button pressed, change the value
CVLADI=CVLADI+1
if cvladi>ulim or cvladi<dlim then cvladi=dlim
ticker=0


here is PCB

9069

richard
- 22nd August 2021, 06:43
Ok, here is the part of code which reads the keys:

pointless snippet . how is adc setup ?

good luck trying to use adc value without passing it through a lpf

a pic of blank pcb is not a schematic

CuriousOne
- 22nd August 2021, 07:26
DEFINE ADC_BITS 8 ' Set number of bits in result
DEFINE ADC_CLOCK 3 ' Set clock source (rc = 3)
DEFINE ADC_SAMPLEUS 50 ' Set sampling time in microseconds

Here is ADC setup. All PBP defaults.

Unfortunately, I don't create schematics - I directly draw PCB, since I can read it in same way, as schematics :)

richard
- 22nd August 2021, 08:27
Unfortunately, I don't create schematics - I directly draw PCB, since I can read it in same way, as schematics

that just explains so much
good luck with your endeavors i'm out

CuriousOne
- 22nd August 2021, 10:41
Well, added 0.1uf capacitor at ADC input, so far, works fine.

Ioannis
- 22nd August 2021, 16:48
This just shows that you have strong interference in the analog inputs because of EMI noise. Where it is coming from?

Well, you can read the PCB as schematics, so as Richard said, good luck here!

If you make a lot of ADC readings, say 20, and then sort them in order, through away the 5 first and last numbers, with the rest 10 make a mean number, then you may get rid off the 100nF capacitor and be more confident of the readings. This makes for a low pass filter in software.

Personally, NEVER use raw adc readings. This is just looking for troubles. A spike can ruin your day. Make many readings and get the best of them to be sure of noise free readings.

Ioannis

CuriousOne
- 22nd August 2021, 17:07
As mentioned above, that noise comes from PWM, PWM is used to adjust brightness of the nixie tubes :)
The HPWM output from the chip is used to modulate bases of all MPSA42 transistors, emitters of which, individually, go into ports of MCU, and collectors are tied to nixie tube cathodes.
That PCB is quite large - about 88x44mm, now I've designed even more compact one, just 70x30mm. Good I haven't put it into production yet - will add capacitor place to PCB.

Actually, reading schematics via PCB is not that hard - just you need to learn it, as you do with normal schematics.

CuriousOne
- 22nd August 2021, 17:10
well if you look at my code, you can see that I here have an special delay loop, which counts how long same value from ADC is being read, but as it turns out, that was not enough.
Oh, and as a note, before soldering capacitor, I tried to add ferrite beads onto wires going to buttons - that helped a bit, previously, if issues were at PWM value of 170, after ferrite beads, only values below 80 were causing issues.
So as I can estimate, the issues from wires acting as antennas. This means, for next revisions, I should add spread spectrum modulation, to reduce EMI sent into air, and maybe, even use shielding.

Ioannis
- 22nd August 2021, 17:13
I would try first the software filtering as I described to you.

Last resort to capacitors. If something changes, then you would remove old caps and put new, larger or smaller???

Ioannis

CuriousOne
- 22nd August 2021, 18:49
Yeah maybe :)
My software skills are quite limited as you can see from my posts :)
And by the way, there was another issue which I've fixed now, and quite likely it was also causing the problems
Due to coding error, I had that brightness adjusting PWM routine called 500 times per second (it was placed in middle dot blink loop)
and when you use HPWM statement, instead of changing the current PWM register, Picbasic stops the pwm generator and restarts it with new values (you can check this with oscilloscope) which causes additional noise generation. Now I moved it into segment refresh routine, which happens once per minute (and keyboard input is deactivated during it), so most likely, it should work without capacitor now, but too lazy to take it apart and unsolder :)

9070

Ioannis
- 22nd August 2021, 21:18
Glad you found the logic error on your code. You did just fine!

Ioannis