Comm issue with 14M2 chip

matchbox

Senior Member
#1
Hi all,
I have one specific 14M2 that requires a hard reset, almost every time I commence an upload to it. If I just hit program, it come up with a comm port error, 8 of 10 times.
I thought it may have been the cable interface or the drivers. But I have checked all that over and its all good. Besides, my other picaxe's have no issue with the hardware.

This chip also went from working last night. To having no outputs driving at all this morning:confused:
So I cleared the chip and tried again...and still nothing. Then I loaded a simple output test program....and all the outputs worked again:confused:
So I then loaded the program that it was running again, and it is working as it should now.

What I'm asking, has anyone else encountered this before? I don't want it messing up when I need it to work in this application.
I could just change the Picaxe chip, but its SMD and a pain to get to. So I want to rule out every possibility first.

Thanks
 
#4
Having to use the hard reset for loading software is usually related to your code - blocking commands in the previously loaded and running code in particular.

The only other point I would make is that I would have a 100nF capacitor as close as possible to the PICAXE's power pins. Particularly when driving servos, which I suspect this board is for. However, if other copies of your board do not give trouble, then that is probably not the cause.
 

matchbox

Senior Member
#5
Thanks for the reply Pete.
I did think that it might be code related. And this board is using and ERF module with two serial outputs. One real time data transmission and the other an ID byte. This is sent to a unit that reads out many different faults from other devices.
And the board is also driving a H bridge circuit.

The code is a bit rough. A bit shameful really:rolleyes:

The one odd thing I did to save on standby power with the ERF module and H bridge, was to power the ERF module and H bridge enable, through a high side NPN switch.

I do give pause start up times for the ERF before data transmission etc.

The whole thing works fine. But it is very possible that something in the code is causing problems.
 
Last edited:

darb1972

Senior Member
#6
Weird and erratic behaviour, I'd check the grounding. As Pete also suggested, good rail decoupling placed carefully near the PICaxe is a must.

Just to clarify, you have been using the same design, the same program code and the same PCB in the past, with no changes and no issues? Is that correct? Is it running off the same test supply? Has anything (at all) changed recently?

If you have a scope (microscope) I'd also suggest running over all of the PCB and pay particular attention to the SMD.
 

matchbox

Senior Member
#7
That's correct. It has been working fine in the most part.

I am not sure of the here after effect. But as I mentioned above, the RF module and H bridge driver turn on together, using the same NPN BJT, because I ran out of outputs to drive them individually. And the two together draw 48mA on standby.

A possibility might be that the two turning on and off together could be forwarding a small spike up the output pin and in turn causing corruption in the picaxe output. It is only a SOT-23 with no biasing or current limiting and is high side switched. Maybe the little transistor is having a junction breaking down and feeding 5v into the output?

I ordered a few P channel mosfets to replace this transistor and perhaps make the setup more rugged.

Does the above theory sound logical?
 

hippy

Technical Support
Staff member
#8
Does the above theory sound logical?
Possibly. That you cannot download likely is that it is just waiting for something, not acknowledging the download request without a Hard Reset.

The 'no outputs' situation could be a hardware latch-up or the code simply getting into a situation where there are no outputs and it is not moving on.

Re-downloading the same code could put it into the same situation again or a hardware latch-up not being cleared.

If an output program download works it may be that it was just the code jammed up going nowhere, rather than a hardware latch-up.

I don't know if it would be the power switching transistor latching up an output or whether changing that would fix things. If a changes fixes things it might suggest that was the cause.

It's almost impossible to say what's gone wrong when one can't see what's going on inside the 'black box'. It might be possible to alter the code so it indicates where it is, what it's doing, and what the outputs should be so you can get a better idea of what's going on when things stop working as expected.
 

darb1972

Senior Member
#9
Yeh matchbox, you really need to post your code and schematics for further help. As Hippy said, it's all a bit "black box" at the moment. Not sure why you don't have the schematics? Is it your design? At least post the code so others can see the structure. Everyone here is really helpful so the more information you give, the more chance you have of someone helping you resolve it. It's all speculation at the moment.

I'm not convinced that changing what was a working hardware design is necessarily going to sort out the issue. Did ANYTHING change recently? Any (external) hardware changes? Any changes to the code?

Here's what might seem like an obvious question, do you have another board (populated) with the same components AND loaded with the same code? If so, is it working?
 
#10
The one odd thing I did to save on standby power with the ERF module and H bridge, was to power the ERF module and H bridge enable, through a high side NPN switch.
Are you sure that is correct? It is most unusual to use an NPN as a high-side switch. When using an NPN as a high-side switch, you will struggle to get the base voltage high enough to turn it on fully.
 
#11
Thanks for the reply's. I am waiting for the P channel FETs to arrive before I rewire those outputs. But any ideas, on streamlining the code, or potential problems that could be causing this; would be appreciated.
I don't have schematics because I just designed the board on CAD and had it made. I had the schematic layout on paper at the time.

The code is for a motorized valve operated water tank first flush system. It uses a peizo pressure transducer to measure water level in the flush dump pipe, and from that note the amount of times a flush has to occured.
The code has a lot of extras, to take into account every scenario. Using current sensing to monitor if the valve gets jammed when closing and a timing backup, and sensor failure.
It also transmits the dump pipe water level back to a monitor unit to show percentage. and when the flush is complete.
The code is a bit mish mash, but it also works in conjunction with the monitor unit that looks a many other devices.
And being that all these devices use the same board, with one 14M2 picaxe. It was difficult to have live serial data, when that One picaxe was performing other real time computations.

I cut a battery check sub out. So the code would fit.
 
#12
Code:
#picaxe 14M2
 setfreq M16                                                        
 low c.0                                                            
 setint %00000100,%00000100                                          
 symbol open_timer = b0                                              
 symbol loopcounter = b1
 symbol flush_count = b4                                             
 symbol scan_time = b5                                               
 symbol post_rain =b6                                                
 symbol volts = b7                                                   
 symbol open = b8                                                   
 symbol check = b9                                                   
 symbol cmd_ord = b16                                               
 symbol LowPwr_state = b17                                           
 symbol rain_check = w1                                                      
 symbol current_load = w5                                            
 symbol water_level = w6                                            
 symbol ref_point = w7                                               
 symbol WL = w13                                                    
 symbol drive = b.4                                                 
 symbol direction = b.5                                              
 symbol filter_clean = b.2                                           
 symbol enable = c.1                                                 
 read 80,flush_count                                                 

 
 
standby:     
 high enable : high direction : high drive                                   
 gosub valve_overload                                                        
 let time=0
 do
 for loopcounter = 1 to 120                                                  
 fvrsetup FVR2048	                                                           
 adcconfig %011		                                                      
 readadc10 b.3, water_level                                                
 if water_level>240 and water_level<=880 then high enable pause 120         
 let WL = water_level min 1 - 235 / 6                                        
 serout c.0,n4800_16,(87,76,WL,flush_count)
 elseif water_level<=240 or water_level>880 then let WL=0 pause 120         
 serout c.0,n4800_16,(87,76,WL) 
 pause 200 low enable endif

 if water_level>880 and post_rain=1 and time<43200 then                      
 let flush_count=3 : write 80,flush_count : post_rain=0 goto flush_control  
 elseif flush_count>=1 and time>=43200 then let flush_count=0                
 write 80,flush_count
 
 elseif water_level>880 then inc flush_count : write 80,flush_count          
 goto flush_control endif                                                    
                                                    
 pause 4000
 if time>65000 and water_level=>240 then let time=0 high enable                   
 low direction : high drive pause 16000 low drive pause 60000 goto standby   
 
 elseif time>65000 and water_level<240 then post_rain=0 time=0 endif         
 
 next loopcounter 
                                                         
 loop


flush_control:
 if water_level>880 and flush_count=4 then                              
 flush_complete: 
 flush_count=0 : write 80,flush_count : high enable
 for loopcounter = 1 to 80                                              
 serout c.0,n4800_16,(103,111,%00000111)                                
 pause 200
 next loopcounter
 low enable
 goto tank_filling endif                                                 

 high enable : low direction : high drive let time=0                    
 pause 40
 for loopcounter = 1 to 20
 fvrsetup FVR1024	                                                      
 adcconfig %011		                                                	 
 readadc10 b.1,current_load                                             
 pause 20
 if current_load>=45 then let current_load=45 exit endif
 next loopcounter

 do
 fvrsetup FVR2048	                                                     
 adcconfig %011		                                                 
 readadc10 b.3, water_level
 if water_level<750 and water_level=>400 then high filter_clean         
 elseif water_level<400 and water_level>250 then low filter_clean       

 elseif water_level=<250 and water_level>100 then pause 20000           
 goto standby  

 elseif time>40 and current_load=45 and water_level>500 then             
 high direction : high drive let flush_count=4 gosub valve_overload     
 goto flush_complete:                                                  
 
 elseif time>50 and water_level>880 or water_level<50 then             
 let time=0 goto failure endif

 if time=>5 and time=<10 then low drive                                                           
 elseif time>10 then low filter_clean endif                             
 loop


tank_filling:
 let time=0 open_timer=0
 do
 fvrsetup FVR2048	                                                          
 adcconfig %011		                                                   	 
 readadc10 b.3, water_level
 if time>3600 and water_level>=850 and cmd_ord=0 then let open_timer=time+1 
 cmd_ord=1 : high enable : low direction : high drive 
 
 elseif time>3600 and water_level<850 and water_level>100 and cmd_ord=0 then
 exit 
 
 elseif time>3600 and water_level<=100 and cmd_ord=0 then goto failure endif
	
 if time>=open_timer and cmd_ord=1 then let cmd_ord=2 : low drive          
 
 elseif water_level<750 and cmd_ord=2 then let time=0 : cmd_ord=0          
 high direction : high drive exit endif                                     
 loop                                                                       
 
 gosub valve_overload                                                       
 
 fvrsetup FVR2048	                                                          
 adcconfig %011		                                                    
 readadc10 b.3, water_level                                                 
 let ref_point = water_level                                                
 
 for loopcounter = 1 to 60                                                  
 pause 8000
 fvrsetup FVR2048	                                                          
 adcconfig %011		                                                    	 
 readadc10 b.3, water_level 
 if water_level > ref_point then let rain_check =  water_level - ref_point  
 elseif water_level < ref_point then let rain_check = 0 endif               
 next loopcounter
 
 if rain_check >60 then let w1=0 w7=0 goto tank_filling                     
 elseif rain_check<=60 and check=0 then let check=1 w1=0 w7=0              
 goto tank_filling 
 
 elseif rain_check<=60 and check=1 then let check=0 w1=0 w7=0               
 high enable : low direction : high drive pause 16000 low drive pause 60000    
 post_rain=1 goto standby endif                                             


valve_overload:
 let time=0
 for loopcounter = 1 to 43
 pause 400                                                            
 fvrsetup FVR1024	                                                     
 adcconfig %011		                                              	 
 readadc10 b.1,current_load                                            
 if current_load>48 and loopcounter>12 and open=0 then                
 low direction pause 16000 high direction let open=1 
 goto valve_overload 
 elseif current_load>47 and loopcounter>12 and open=1 then let open=0  
 goto stalled_valve endif
 next loopcounter 
 low drive low enable   
 return                                               


failure:
 do
 high enable
 let scan_time = 1200 
 for loopcounter = 1 to 5
 pause scan_time                                                                        
 serout c.0,n4800_16,(103,111,%00001001)                               
 let scan_time = scan_time + 1200                                    
 next loopcounter 
 loop


stalled_valve:
 low direction pause 6000 low drive high direction                   
 do
 let scan_time = 1200 
 for loopcounter = 1 to 5
 pause scan_time                                                                       
 serout c.0,n4800_16,(103,111,%00001000)                              
 let scan_time = scan_time + 1200                                    
 next loopcounter 
 loop 



interrupt:
 if pinc.1=1 then let LowPwr_state=1                                  
 elseif pinc.1=0 then let LowPwr_state=0 endif
 high enable
 pause 4000                                                          
 if pinc.2=1 and pinb.5=1 then high filter_clean                      
 low direction high drive pause 16000 low drive pause 12000 
 low filter_clean 
 elseif pinb.5=0 then high direction high drive pause 16000 low drive 
 elseif pinb.5=1 then low direction                                   
 high drive pause 16000 low drive endif
 if LowPwr_state=1 then high enable                                   
 elseif LowPwr_state=0 then low enable endif
 setint %00000100,%00000100                                           
 return
 
Last edited:
#13
I'm no code guru, but your very first gosub/call "valve_overload" has no "return" (that I can see). You must have a return for every gosub. Not suggesting that's your issue, but it needs to be rectified.
 
#14
Sorry about that. Your right. It was just when I was cutting all of the comments out, to get it below 10000 characters to post. That I cut that return out as well:eek: I placed it back in there so not to confuse anyone else.
 
#15
Might be best to post your code exactly how you wrote it as I see many lines containing multiple commands with no separator (colon). Not sure if that's how it actually was or whether your modifications to make it fit removed vital parts. So the folks here can spot issues it's best you present the code as is.

My advice is to simply split the code over several convective posts.
 
#16
What you see is the way the code worked Darb:) I just added colons for my own code separation reference. I have never needed them to make any program work.

The more I think about it. I think Hippy and Pete might have the possible cause. That the transistor is not always turning hard on. This in turn is causing the code to lockup in the serout section. Thinking back when writing this. I needed to have the pause timer that surrounded and serout command, very close to what there are in the program. I also needed the clock speeds of this unit and the monitor unit to both be at 16Mhz, for more reliable operation.

I will leave it till the P channel fet arrives and report back on my results, after much testing.

Code:
do[COLOR="#FF0000"][/COLOR]
 for loopcounter = 1 to 120                                                  
[COLOR="#FF0000"] fvrsetup FVR2048	                                                           
 adcconfig %011		                                                      
 readadc10 b.3, water_level                                                
 if water_level>240 and water_level<=880 then high enable pause 120         
 let WL = water_level min 1 - 235 / 6                                        
 serout c.0,n4800_16,(87,76,WL,flush_count)
 elseif water_level<=240 or water_level>880 then let WL=0 pause 120         
 serout c.0,n4800_16,(87,76,WL) 
 pause 200 low enable endif[/COLOR]

 if water_level>880 and post_rain=1 and time<43200 then                      
 let flush_count=3 : write 80,flush_count : post_rain=0 goto flush_control  
 elseif flush_count>=1 and time>=43200 then let flush_count=0                
 write 80,flush_count
 
 elseif water_level>880 then inc flush_count : write 80,flush_count          
 goto flush_control endif                                                    
                                                    
 pause 4000
 if time>65000 and water_level=>240 then let time=0 high enable                   
 low direction : high drive pause 16000 low drive pause 60000 goto standby   
 
 elseif time>65000 and water_level<240 then post_rain=0 time=0 endif         
 
 next loopcounter
 
#17
Might be best to post your code exactly how you wrote it as I see many lines containing multiple commands with no separator (colon). Not sure if that's how it actually was or whether your modifications to make it fit removed vital parts. So the folks here can spot issues it's best you present the code as is.

My advice is to simply split the code over several convective posts.
While it is good/recommended practice to use colons ( : ) as newline separators as a result of historic backward compatibility the PE does allow a space to also be a Newline separator. While most of the time the PE does successfully determine when a space in the source code represents a newline, it can fail and result in wrong code downloaded to the PICAXE chip.
Thus YES it is highly recommended that colons be used for indicating new lines where multiple code lines are put on a single text line.
 
#18
While it is good/recommended practice to use colons ( : ) as newline separators as a result of historic backward compatibility the PE does allow a space to also be a Newline separator.
Thanks for that Westy. I didn't know that. I thought it was either a new line or a colon. That explains why matchbox's code passed syntax and was loaded into the PICaxe. Despite knowing that a "space" is acceptable syntax, I'll stick to new lines (or worst case, colons). Too confusing otherwise. IMHO, it makes the code hard to follow.

While most of the time the PE does successfully determine when a space in the source code represents a newline, it can fail and result in wrong code downloaded to the PICAXE chip.
May I ask what might be a curly question and ask how can fail, pass syntax and be downloaded to a PICaxe? I thought the editor ran a syntax prior to compiling the code and before loading into the PICaxe. Can it "miss" issues such as this???

Thank Westie.

PS: Sorry, I'm still on my steep leaving curve!
 

hippy

Technical Support
Staff member
#21
the PE does allow a space to also be a Newline separator.
I think it is more correct to say that PE6 will tolerate spaces where colons should be used but aren't. PE6 will try to do its best when colons are missing but can potentially get confused, give syntax errors or in the worst case take the program other than may have been intended.

The best recommendation is to write code with one command per line with indentation used to show where a block command starts and ends and what is inside those blocks.

Where it may make things more obvious, more understandable, or aesthetically pleasing; multiple commands can be places on one line. Where that's done it is strongly recommended to use colons to separate each statement.

The main reason isn't to ensure PE6 can compile a program without syntax error, but to make a program more readable, more understandable, easier to verify or debug. That's particularly so for code presented to others but also applies to the original author if they come back to it some time in the future.

I have to admit I found the code in post 10 almost impenetrable, was surprised when it actually compiled without syntax errors.

There's nothing wrong with the code per se, but I wouldn't know where to start to understand it without unravelling it and visualising it in a way I can more easily comprehend it. Without doing that I simply can't make a guess as to whether it's working as one wants or whether there's something in there which may have led to the problems initially reported.

For example, I'd have taken this chunk of "wall of code" as Phil Spector might have described it -

Code:
if water_level>240 and water_level<=880 then high enable pause 120         
let WL = water_level min 1 - 235 / 6                                        
serout c.0,n4800_16,(87,76,WL,flush_count)
elseif water_level<=240 or water_level>880 then let WL=0 pause 120         
serout c.0,n4800_16,(87,76,WL) 
pause 200 low enable endif
and have had this -

Code:
if water_level >= 241 and water_level <= 880 then
  high enable
  let WL = water_level - 241 / 6 + 1                                        
  serout c.0,n4800_16,(87,76,WL,flush_count)
else
  low enable
  let WL = 0 
  serout c.0,n4800_16,(87,76,WL) 
endif
 
#22
Thank you to Westie and Hippy for the clarification of preferred code layout. As mentioned, I didn't realise that a space could seperate code commands, but, I won't be using them as I'd much prefer to use new lines and indentation. I'm not strong in the code side of things so any format that helps to clarify structure is the way to go.
 
#23
Thanks for the input Hippy.
I do agree, that writing statements line by line, is far more readable for others and may certainly reduce the chance of a compiler error.
I suppose that I have just got used to writing this way, because I find it easier to scroll up and down less lines in the page, when looking through different subroutines.
And have just found that the syntax checks out....So I've stuck with it.
Your layout is very tidy, though:)

I'm grateful for your input and different layout. What you written looks like it would work. But due to my interaction between devices. It is not likely too. Not having a go at you. Indeed, I would prefer to use your style of format here. I even went for this type of thing at first.

Your quote - "I have to admit I found the code in post 10 almost impenetrable, was surprised when it actually compiled without syntax errors."....
You had me rolling around in laughter! :D

I tend to do things in odd ways sometimes. And just build upon things until they work. Rather than follow every rule, word by word;)

The reason it is written this way, is due to the way the code between multiply different devices interacts with the monitor/diagnostic unit. It was the only way that I could keep the individual devices performing their tasks, while still having some form of serial communication with this monitor/diagnostic unit.
Ideally, in hindsight, it would have been better to make a board with 2 x 14M2. It would have being far better.
And even now....If I had the time, I would rewrite them all again and try to fix up things in a possibly better way. But I don't have weeks and weeks to spend on them all.

Still waiting on the mail for those FET's to turn up.
 
Last edited:
#24
I thought I better explain my "wall of code", Hippy;)
Before I start on the part you reviewed. I'll talk about the way I look at things.
For example, this program for a water tank first flush, could have be cut down to 300bytes. In fact it would work at that 98% of the time.
Although it would have lacked 3/4 of its functionality, and if it got snagged the other 2% of the time. I would have had to chase down, how and why... in the rain.

I really like looking at other peoples code snippets, to gives me ideas of how to simplify my own.
Mine does come across as a mess. But I believe a code should take into account, and deal with all possibilities.

Here is a list of all this program does -

1)Dumps the first flush pipe 3 times. Can be set according to the roof, gutter or dump pipe length.
2)If an extreme down pour occurs and flush pipe level doesn't drop when the valve opens. Then close valve for tank filling after 40sec(water coming in faster, than can dumped)
3)less than 12hours have passed from the last rain fall. Only dump the flush pipe once, if it starts to rain again.
4)Not enough rain occurs for a complete roof flush. Reset flush counter if no more rain occurs in over 12hours.
5)After flushes are complete. The system allows tank filling for 60mins, before it checks if its still raining, at 1hr then 2hr, no rain after 2hr, dump pipe.
6)Each time the flush pipe is dumped, a back flush fresh water jet cleans the inlet pre-filter.
7)Valve close overload detection. In case valve gets jammed by a sticks etc. It will open after jamming then try to close again, before alarming.
8)Manual valve override switch, to allow manual valve opening/closing and back flush pre-filter cleaning.
9)Check in dry conditions if dump pipe has water in it every 18hrs. If so, empty pipe to prevent stagnation (water from dew or frost)
10)System diagnostic - Low battery volts - Jammed valve while closing - Sensor or valve motor failure - monitors real time , the dump pipe water level in percentage, then tells when flushing is complete(tank is now filling).

As for that part you mentioned Hippy. It measures the pressure sensor output(which interprets water level). Then transmits the percentage of level to the diagnostic unit, to display.
It looks at the minimum sensor level at 2v FVR = 235. And the dump trigger level = 880. Then divides it by a rounded percentage difference between the both = 6. It doesn't have to be totally accurate. Then transmits it.
(min 1) prevents the percentage going below 1%, because a suction in the sensor line, can pull it below 235 on the sensor output.
When its outside those boundaries. It transmits WL=0. This clears the OLED display, at the received end.
And the Enable, turns the RF module ON and OFF.
While the pauses, give the module time to boot up.
 
#25
At the end of the day, no matter
how tidy and well formatted or
How messy and compacted

If all the statements are the same, then
The code as tokenized and loaded into your PICACE will occupy the same space for the same functionality
 

hippy

Technical Support
Staff member
#26
And the Enable, turns the RF module ON and OFF.
While the pauses, give the module time to boot up.
Thanks. That explains the PAUSE and the ordering; one cannot turn the RF off and then transmit, it has to be transmit and then turn off.

That makes perfect sense. My misunderstanding came from not being entirely sure what you have, what controls what.
 
#27
Hi all,
I just thought I'd give an update on my findings. I did change the FET to a P channel. And it is more responsive with the RF module turn on time.
But the cause of the error, as a couple of you thought, was in the program.
I messed up. In the place where I have a serial transmit, incremented scan timer. I had a byte variable and it should have been a Word.
Under specific circumstances of the codes operation, it would transmit once then lock up the output. That was also why it would not except a download without a hard reset.
Simple thing really:eek:

Thanks for listening guys
 
Top