Tonnage weigted average problem


Gammatech

Recommended Posts

Hi

I have three channels updated every second from a serial input. The first is the current Tonnes per hour from a weigher on the conveyor belt, the second is the instantaneous Ash content of the material on the belt as a percentage (0-100%) and the third is the instantaneous Moisture content of the material on the belt again as a percentage. My application needs to display and store the tonnage weighted average (Ash & Moisture) either for a specific period or a specific tonnage (user selected) I have all the user selection code working fine which sets a flag if accumulation into the average should occur. (BeginSeq(AccumulateToBatch)

The sequence to accumulate each seconds data simply takes the TonnesThis Second (A declared Global variable) (TonnesPerHour/3600) and multiplies this by the current instantaneous quality (Ash, Moisture) percent to get the AshTonnesThisSecond and MoistureTonnesThisSecond. These are each accumulated to running totals called BatchAshTonnes and BatchMoistTonnes. A seperate accumulation of the TonnesThis Second is made into BatchTonnes. By dividing BatchAshTonnes by BatchTonnes I get the BatchAsh. (Similarly for moisture) This works fine. This sequence is called "AccumulateToBatch"

// Sequence AccumulateToBatch
TonnesThisSecond = TPH[0]/3600
AshTonnesThisSec = TonnesThisSecond * Ash[0]
MoistTonnesThisSec = TonnesThisSecond * Moisture[0] 
// May be belt and braces but just in case this is the first value accumulated
If(IsEmpty(BatchAshTonnes[0]))
   VM1Val = AshTonnesThisSec
Else
   VM1Val = BatchAshTonnes[0] + AshTonnesThisSec
EndIf
// AshTonnesThis second will have indeterminate time so insert time before storage
VM1Val = InsertTime(VM1Val,SysTime(),-1)  
BatchAshTonnes.AddValue(VM1Val)
If(IsEmpty(BatchMoistTonnes[0]))
   VM1Val = MoistTonnesThisSec
Else
   VM1Val = BatchMoistTonnes[0] + MoistTonnesThisSec
EndIf
 // MoistTonnesThis second will have indeterminate time so insert time before storage
VM1Val = InsertTime(VM1Val,SysTime(),-1) 
BatchMoistTonnes.AddValue(VM1Val)
If(IsEmpty(BatchTonnes[0]))
   VM1Val = TonnesThisSecond
Else
   VM1Val = BatchTonnes[0] + TonnesThisSecond
EndIf
// TonnesThis second will have indeterminate time so insert time before storage
VM1Val = InsertTime(VM1Val,SysTime(),-1) 
BatchTonnes.AddValue(VM1Val)
If(BatchTonnes[0] > 0)
   VM1Val = BatchAshTonnes[0] / BatchTonnes[0]
   BatchAsh.AddValue(VM1Val)
   VM1Val = BatchMoistTonnes[0] / BatchTonnes[0]
   BatchMoisture.AddValue(VM1Val)
Else
   VM1Val = 0
   // VM1Val will have indeterminate time so insert time before storage
	VM1Val = InsertTime(VM1Val,SysTime(),-1) 
   BatchAsh.AddValue(VM1Val)
   BatchMoisture.AddValue(VM1Val)
EndIf

At the end of the Batch I call a sequence to close the batch which stores the final tonnes accumulated into the batch (BatchTonnes), the BatchAsh and the BatchMoisture. This sequence also has to set the running totals, (BatchTonnes, BatchAshTonnes anf BatchMoistTonnes) to zero ready for the next batch. This sequence is called "CloseBatch"

// Sequence CloseBatch.
// Transfers the resultant BatchAsh, BatchMoisture  and BatchTonnes to their respective 'Final' channels and resets them to zero
// Also stores BatchStart and BatchEnd times in their 'Final' channels. It might be possible to use the .Time element of a Final channel rather than the BatchEndFinal store. but this seems clearer.

BatchAshFinal.AddValue(BatchAsh[0])
BatchMoistFinal.AddValue(BatchMoisture[0])
BatchTonnesFinal.AddValue(BatchTonnes[0])
BatchStartFinal.AddValue(BatchStart)
BatchEndFinal.AddValue(BatchEnd)
// reset accumulators to zero
BatchAshTonnes.AddValue(0)
BatchMoistTonnes.AddValue(0)
BatchAsh.AddValue(0)
BatchMoisture.AddValue(0)
BatchTonnes.AddValue(0)

The problem is that it seems the channels used for the accumulation don't always actually reset to zero properly (The BatchTonnes always does?) as some times the next batch has a high BatchAsh and or BatchMoisture shown. I can't see where I'm going wrong, any ideas?

Martin

Link to comment
Share on other sites

So if you manually (from command / alert) do BatchMoistTonnes.AddValue(0) do you get 0 into the channel? How is the channel setup? If you run close batch manually and then look at the BatchMoistTonnes channel, it doesn't show 0? Are you sure you aren't getting an error message that is causing the sequence to stop short?

Link to comment
Share on other sites

Hi,

I can't see any alerts indicating a problem and as one would expect zeroing a value at the command line does in fact make the value go to zero.

Perplexed, I changed the accumulators BatchAshTonnes and BatchMoistTonnes to Global variables so the zeroing was not calling AddValue but was simply an assignment BatchAshTonnes = 0.0 and similar for the moisture. This behaved exactly the same, watching the values they generally went to zero at each batch end but sometimes did not. So I made another Global variable ZeroCount = 0.0 and then did the rather strange addition:

While(BatchAshTonnes > 0)
  BatchAshTonnes = 0.0
  ZeroCount ++
EndWhile

With this code in place (ZeroCount is reset to 0 on entry to the CloseBatch sequence) Every thing works well all of the time and ZeroCount only gets to 1 MOST of the time. Occasionaly however ZeroCount shows up as 2. So far I have not seen it go any higher than 2.

So now I am perplexed on a higher intellectual plane! Anyone looking at the code would say "What on earth is that for" The fact is however that it works while a simple assignment to zero does not always.

Any further thoughts?

Martin

Link to comment
Share on other sites

Ah, the challenges of multithreaded programming. You are almost certainly changing these values from somewhere else that is running concurrently. I wonder if you went back to your BatchAshTonnes channel with the addvalue() if you see it set to 0 in the history and then immediately being changed to another value.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.