Menu
JAQForum Ver 19.10.27

Forum Index : Microcontroller and PC projects : read out carolling christmas bells

   Page 2 of 5    
Posted: 08:02pm
03 Nov 2025
Copy link to clipboard
Frank N. Furter
Guru

@Volhout:

Thanks for your link - the project looks very interesting too.


@phill99:

Thanks! Now I just have to solder the voltage dividers together. Let's see if I can get around to it this week...



I just unscrewed the electronics again. A proprietary µC with 2x ULN2003 was installed. I bought it in 1994...
 
Posted: 05:54am
04 Nov 2025
Copy link to clipboard
phil99
Guru


A rudimentary test setup with two PicoMites. The first is a simulated xylophone player with a Sub to make a random sequence of notes. The second Pico records the output of the first. GP0 - GP11 connect to GP0 - GP11 on the other, plus Gnd.

The Player and it's output.
'Xylophone player
Dim float SPD=50 'solenoid pulse duration
Dim integer n, Bell.note
Dim float Bell.time, interval

MakeFile 'Sub to create a test file

For n=0 To 11
 SetPin MM.Info(pinno "GP"+Str$(n)),DOUT
Next

Open "BellSample.dat" For Input As #1

Print "Input time","Solenoid(s)",,"Output time", "interval"

Timer = 0

For n=0 To 20
 Input #1, Bell.time, Bell.note 'get the data
 Do While Timer < Bell.time : Loop 'wait for next note
 Port(1,2,4,4,9,4,14,2) = Bell.note 'ring the bells
 Print Bell.time, Bin$(Bell.note,12),, Timer, Bell.time-interval
 Pause SPD 'solenoid pulse duration
 Port(1,2,4,4,9,4,14,2) = 0 'all solenoids off
 interval = Bell.time
Next

Sub MakeFile
 Open "BellSample.dat" For Output As #1
 For n=0 To 20
 Inc Bell.time, (Rnd * 400 + 100) 'random intervals from 100 to 500mS
 Bell.note = (1 << Fix(Rnd * 12)) Or (1 << Fix(Rnd * 12)) ' ring 2 random bells
 Print #1, Bell.time;","; Bell.note
 Print Bell.time, Bin$(Bell.note,12)
 Next
 Print :Print
 Close #1
End Sub

End
> list "BellSample.dat"
481.4629415, 2052
685.9638557, 1088
1068.890898, 8
1426.471311, 1280
1703.731011, 513
2041.607806, 10
2521.895152, 2176
2973.670426, 272
3319.063016, 1026
3594.936921, 12
3897.402463, 320
4246.852904, 65
4572.434282, 66
4912.247204, 24
5308.362597, 2056
5558.917196, 96
6047.464737, 144
6296.664923, 17
6690.30336, 128
7141.14529, 9
7640.742658, 576
>
> RUN
Input time      Solenoid(s)             Output time     interval
481.4629415    100000000100             482.564         481.4629415
685.9638557    010001000000             686.728         204.5009142
1068.890898    000000001000             1069.802        382.9270423
1426.471311    010100000000             1427.26         357.580413
1703.731011    001000000001             1704.547        277.2597
2041.607806    000000001010             2042.513        337.876795
2521.895152    100010000000             2522.739        480.287346
2973.670426    000100010000             2974.523        451.775274
3319.063016    010000000010             3319.816        345.39259
3594.936921    000000001100             3595.753        275.873905
3897.402463    000101000000             3898.184        302.465542
4246.852904    000001000001             4247.658        349.450441
4572.434282    000001000010             4573.378        325.581378
4912.247204    000000011000             4912.997        339.812922
5308.362597    100000001000             5309.247        396.115393
5558.917196    000001100000             5559.793        250.554599
6047.464737    000010010000             6048.339        488.547541
6296.664923    000000010001             6297.477        249.200186
6690.30336     000010000000             6691.216        393.638437
7141.14529     000000001001             7141.996        450.84193
7640.742658    001001000000             7641.568        499.597368
>

And the recorder.
'Reading the 12 outputs of a chiming bells ornament. (untested)
'It records the time (mS) when each bell is struck and the number of the bell(s)

Dim integer n, tmr

For n=0 To 11
SetPin MM.Info(pinno "GP"+Str$(n)),DIN
Next

Open "RecordBells.dat" For Output As #1
Print "Timer", "Solenoid", "Interval mS"

Do : Loop Until Port(gp0,12) 'wait for the first pulse
Timer = 0

For n = 0 To 20 'or whatever the sequence length is
 tmr = Timer
 Do : Loop Until Port(gp0,12) 'wait for a chime
 Print #1, Timer; ",", Port(gp0,12)
 Print Timer; ",", Bin$(Port(gp0,12),12),
 Pause 59 'Wait for solenoid pulse to end.
'longer than a solenoid pulse, shorter than the shortest interval between chimes
 Print Timer-tmr
Next

End
>
Timer   Solenoid        Interval mS
0.63   100000000100     60.155
204.649        010001000000     204.037
587.569        000000001000     382.963
945.156        010100000000     357.554
1222.416       001000000001     276.773
1560.298       000000001010     337.668
2040.59        100010000000     479.964
2492.343       000100010000     451.745
2837.741       010000000010     345.127
3113.62        000000001100     276.019
3416.073       000101000000     302.458
3765.537       000001000001     348.913
4091.158       000001000010     325.534
4430.916       000000011000     339.332
4827.065       100000001000     395.442
5108.852       000001100000     281.836
5566.197       000010010000     456.61
5815.364       000000010001     248.781
6209.013       000010000000     393.396
6659.849       000000001001     450.249
7159.442       001001000000     498.807
>
> list "RecordBells.dat"
0.31,   2052
204.47,     1088
587.42,     8
944.987,    1280
1222.252,   513
1560.135,   10
2040.435,   2176
2492.191,   272
2837.587,   1026
3113.471,   12
3415.919,   320
3765.39,    65
4090.978,   66
4430.765,   24
4826.909,   2056
5077.469,   96
5566.021,   144
5815.193,   17
6208.862,   128
6659.704,   9
7159.296,   576
>

It's been a wet day so stuck indoors.
Edited 2025-11-04 16:01 by phil99

Footnote added 2025-11-04 21:28 by phil99
In the first program (Xylophone player) the Port command can be simplified to  Port(gp0,12) from Port(1,2, 4,4, 9,4, 14,2)
 
Posted: 06:11am
04 Nov 2025
Copy link to clipboard
Volhout
Guru

PORT(GP0,12) ?

Volhout
 
Posted: 06:27am
04 Nov 2025
Copy link to clipboard
phil99
Guru


Yes, the Port Function behaves differently to the Port Command. It works so I wont complain!
 
Posted: 06:14am
05 Nov 2025
Copy link to clipboard
phil99
Guru


A slightly less rudimentary test setup with two PicoMites.
The previous one assumed that when more than one bell is sounding they have been struck at exactly the same time. It also required prior knowledge of the solenoid pulse duration. This recorder simply records every change in state of the Port, so the file is twice as long.
The player program has been changed to read the new file format.

The first program is a simulated xylophone player with a Sub to make a random sequence of notes. The second Pico records the output of the first. GP0 - GP11 connect to GP0 - GP11 on the other, plus Gnd.

The Player and it's output.
'Xylophone player
Dim float SPD=40 'solenoid pulse duration
Dim integer n, Bell.note, Steps=40 'number of on/off transitions in the sequence
Dim float Bell.time, interval

MakeFile 'Sub to create a test file

For n=0 To 11
 SetPin MM.Info(pinno "GP"+Str$(n)),DOUT
Next

Open "BellSample.dat" For Input As #1

Print "Input time","Solenoid(s)",,"Output time", "interval"

Timer = 0

For n=0 To Steps
 Input #1, Bell.time, Bell.note 'get the data
 Do While Timer < Bell.time : Loop 'wait for next note
 Port(gp0,12) = Bell.note 'start / end solenoid pulse
 Print Bell.time, Bin$(Bell.note,12),, Timer, Bell.time-interval
 interval = Bell.time
Next
Port(gp0,12) = 0

Sub MakeFile
 Open "BellSample.dat" For Output As #1
 For n=0 To Steps\2
   Inc Bell.time, (Rnd * 400 + 100) 'random intervals from 100 to 500mS
   Bell.note = (1 << Fix(Rnd * 12)) Or (1 << Fix(Rnd * 12)) ' ring 2 random bells
   Print #1, Bell.time;","; Bell.note 'solenoid pulse start
   Print Bell.time, Bin$(Bell.note,12)
   Print #1, Bell.time+SPD;","; 0 'solenoid pulse end
   Print Bell.time+SPD, Bin$(0,12)
 Next

 Print #1, Bell.time+SPD;","; 0 'solenoid pulse end
 Print Bell.time+SPD, Bin$(0,12)
 Close #1
End Sub

End
Input time      Solenoid(s)             Output time     interval
486.3169189    001001000000             487.327         486.3169189
526.3169189    000000000000             527.135         40
745.3778474    000010010000             746.32  219.0609285
785.3778474    000000000000             786.107         40
950.862063     100000001000             951.615         165.4842156
990.862063     000000000000             991.582         40
1062.104325    001010000000             1062.867        71.242262
1102.104325    000000000000             1102.979        40
1325.211812    100000001000             1326.068        223.107487
1365.211812    000000000000             1366.039        40
1650.079234    010000000010             1650.968        284.867422
1690.079234    000000000000             1690.885        40
1878.4487      100000000010             1879.164        188.369466
1918.4487      000000000000             1919.161        40
2074.975631    000000001010             2075.797        156.526931
2114.975631    000000000000             2115.882        40
2412.865766    010000000001             2413.705        297.890135
2452.865766    000000000000             2453.66         40
2842.634445    001000000001             2843.555        389.768679
2882.634445    000000000000             2883.356        40
3010.766345    000010001000             3011.492        128.1319
3050.766345    000000000000             3051.47         40
3309.987316    000000100001             3310.866        259.220971
3349.987316    000000000000             3350.739        40
3480.15817     000000000100             3480.935        130.170854
3520.15817     000000000000             3520.883        40
3791.819801    000010000001             3792.752        271.661631
3831.819801    000000000000             3832.671        40
4018.980067    000001010000             4019.741        187.160266
4058.980067    000000000000             4059.769        40
4432.960825    000010010000             4433.82         373.980758
4472.960825    000000000000             4473.721        40
4625.474201    000010010000             4626.292        152.513376
4665.474201    000000000000             4666.194        40
5097.370829    100100000000             5098.205        431.896628
5137.370829    000000000000             5138.071        40
5302.954596    000100000001             5303.746        165.583767
5342.954596    000000000000             5343.803        40
5508.765062    000001100000             5509.487        165.810466
5548.765062    000000000000             5549.457        40
5864.424738    000000000010             5865.252        315.659676

And the recorder.
'Reading the 12 outputs of a chiming bells ornament.
'It records the time (mS) when any solenoid is activated/released and which solenoids(s)

Dim integer n, tmr, Port.now

For n=0 To 11
 SetPin MM.Info(pinno "GP"+Str$(n)),DIN
Next

Open "RecordBells.dat" For Output As #1
Print "Timer",, "Solenoid", "Interval mS"
Print #1, 0; ",", 0
Print "  Waiting to start"
Timer = 0

Do : Loop Until Port(gp0,12) 'wait for the first pulse
Timer = 100

Do While Timer-tmr < 3000
 tmr = Timer
 Port.now = Port(gp0,12)
 Do While (Port(gp0,12) = Port.now) And (Timer-tmr < 3000) : Loop 'wait for a solenoid pulse to start/end

 If Timer-tmr < 2500 Then
   Print #1, Timer; ",", Port.now
   Print Timer, Bin$(Port.now,12), Timer-tmr
  Else
   Print #1, Timer-2950; ",", 0
   Print Timer-2950 Bin$(0,12), Timer-tmr
 EndIf

Loop

Print "Finished - more than 3S since last pulse"
End
Timer           Solenoid        Interval mS
 Waiting to start
140.254        001001000000     40.353
359.159        000000000000     218.23
399.165        000010010000     40.238
564.65 000000000000     165.719
604.634        100000001000     39.707
675.875        000000000000     70.947
715.911        001010000000     39.986
939.016        000000000000     223.086
978.964        100000001000     40.039
1263.855       000000000000     284.924
1303.855       010000000010     39.924
1492.213       000000000000     188.282
1532.243       100000000010     39.315
1688.744       000000000000     155.815
1728.779       000000001010     39.85
2026.637       000000000000     297.706
2100.318       010000000001     73.665
2456.5 000000000000     355.575
2496.421       001000000001     39.495
2624.554       000000000000     127.622
2664.563       000010001000     39.633
2923.786       000000000000     258.854
2963.762       000000100001     39.832
3093.917       000000000000     129.992
3133.928       000000000100     40.001
3405.624       000000000000     271.692
3445.594       000010000001     39.666
3632.743       000000000000     186.81
3672.744       000001010000     39.818
4046.74        000000000000     373.809
4086.757       000010010000     39.832
4239.281       000000000000     152.349
4279.993       000010010000     40.339
4711.24        000000000000     430.317
4751.185       100100000000     39.258
4916.719       000000000000     165.785
4956.745       000100000001     39.814
5122.546       000000000000     165.613
5162.536       000001100000     39.606
5478.212       000000000000     315.28
5479.714       000000000010     0.782
5480.122       000000000000     3000.19
Finished - more than 3S since last pulse
>


Edit.
Copied the file recorded by the second program to the player and played it to the recorder for error checking.
The Port values remain the the same and the timings are within a millisecond or so, except for the first and last may be a bit off. They could easily be fixed in a text editor if required.

So though these programs are quite rough they may be adequate for the task.
Edited 2025-11-05 21:57 by phil99
 
Posted: 07:35pm
05 Nov 2025
Copy link to clipboard
Frank N. Furter
Guru

Hi Phil,

thank you very much for your program and your efforts. Here is the first test:

> run
Timer           Solenoid        Interval mS
 Waiting to start
236.258        111100000000     136.854
902.339        000000000000     665.865
937.376        000000100000     34.897
1136.135       000000000000     198.7
1171.141       000000000100     34.647
1369.905       000000000000     198.453
1404.924       000000000001     34.419
1603.727       000000000000     198.233
1638.74        000000000010     34.254
1837.448       000000000000     197.976
1872.506       000000001000     35
2071.207       000000000000     198.763
2106.25        000000010000     34.744
2304.997       000000000000     198.515
2340.025       100000000000     34.616
2538.694       000000000000     198.226
2602.168       000100000000     63.272
2772.462       000000000000     169.008
2807.494       000001000000     35.054
3006.19        000000000000     198.745
3041.164       000010000000     34.677
3239.889       000000000000     198.413
3274.91        001000000000     34.447
3473.582       000000000000     198.072
3508.574       010000000000     35.105
3559.256000000000000    3000.751
Finished - more than 3S since last pulse
>

The order of the bells is incorrect. I had to solder the wires randomly because it is quite a lot of work to trace them back to the bells.
It would be nice if I could rearrange the bells in the program. The first sequence of notes is all 12 bells from the highest to the lowest note.

Do you have any idea how I can suppress the “000000000000” from the outset?

Unfortunately, the pause between songs is longer than 3 seconds and your program terminates. Which numbers do I need to change to increase the time?

Thank you very much!

Frank
 
Posted: 05:18am
06 Nov 2025
Copy link to clipboard
phil99
Guru


  Quote  The order of the bells is incorrect. I had to solder the wires randomly
The recording program now has a re-ordering program tacked on the end that uses your recorded data for the translation.
  Quote  pause between songs is longer than 3 seconds and your program terminates. Which numbers do I need to change to increase the time?

Here is your data fed to the recorder program via the xylophone player program. After the time-out (now 8S, adjustable near the start of the program) it transposes the bits so they come out in order and saved to file Remapped.dat.
Timer           Solenoid        Interval mS
 Waiting to start
100.687        111100000000     0.788                   0
766.312        000000000000     665.388                         1
801.295        000000100000     34.372                  2
1000.088       000000000000     198.155                         3
1035.041       000000000100     35.111                  4
1233.818       000000000000     198.887                         5
1268.86        000000000001     34.929                  6
1467.64        000000000000     198.709                         7
1502.675       000000000010     34.743                  8
1701.359       000000000000     198.427                         9
1736.455       000000001000     34.525                  10
1935.134       000000000000     198.204                         11
1970.186       000000010000     34.257                  12
2168.927       000000000000     197.996                         13
2203.997       100000000000     35.07                   14
2402.61        000000000000     198.681                         15
2503.209       000100000000     100.596                         16
2636.44        000000000000     132.515                         17
2671.453       000001000000     34.528                  18
2870.127       000000000000     198.195                         19
2905.101       000010000000     34.174                  20
3103.818       000000000000     197.889                         21
3138.833       001000000000     34.908                  22
3337.509       000000000000     198.579                         23
3372.521       010000000000     34.591                  24
3374.023       000000000000     1.094                   25
3874.271       000000000000     8050.349                        26     else
Finished - more than  8000S since last pulse
Remapping solenoids to Remapped.dat

Bell.time       out     Bell.note.out   in      Bell.note.in

100.383         3264   110011000000     3840   111100000000
766.2   0      000000000000     0      000000000000
801.193         1      000000000001     32     000000100000
999.993         0      000000000000     0      000000000000
1034.944        2      000000000010     4      000000000100
1233.72         0      000000000000     0      000000000000
1268.764        4      000000000100     1      000000000001
1467.541        0      000000000000     0      000000000000
1502.583        8      000000001000     2      000000000010
1701.258        0      000000000000     0      000000000000
1736.36         16     000000010000     8      000000001000
1935.037        0      000000000000     0      000000000000
1970.087        32     000000100000     16     000000010000
2168.827        0      000000000000     0      000000000000
2203.891        64     000001000000     2048   100000000000
2402.511        0      000000000000     0      000000000000
2466.009        128    000010000000     256    000100000000
2636.304        0      000000000000     0      000000000000
2671.347        256    000100000000     64     000001000000
2870.031        0      000000000000     0      000000000000
2905.002        512    001000000000     128    000010000000
3103.724        0      000000000000     0      000000000000
3138.736        1024   010000000000     512    001000000000
3337.414        0      000000000000     0      000000000000
3372.423        2048   100000000000     1024   010000000000
3373.928        0      000000000000     0      000000000000
3874.153        0      000000000000     0      000000000000
>

> list "Remapped.dat"
100.374,    3264
766.191,    0
801.213,    1
999.977,    0
1034.977,   2
1233.738,   0
1268.759,   4
1467.566,   0
1502.576,   8
1701.294,   0
1736.361,   16
1935.058,   0
1970.083,   32
2168.836,   0
2203.86,    64
2402.54,    0
2466.011,   128
2636.334,   0
2671.317,   256
2870.025,   0
2905.019,   512
3103.771,   0
3138.752,   1024
3337.446,   0
3372.426,   2048
3373.853,   0
3874.143,   0
>


  Quote  Do you have any idea how I can suppress the “000000000000” from the outset?
Do you mean just the console output or the output file? if just the console output then it could be done. This version of the program requires the "0" values to be recorded so the player will know when to switch the solenoids off. It also allows more than one chime at a time without them having to be exactly synchronized. If none of the music requires that we could revert to something like the earlier program. The earlier version didn't record the “000000000000” as its matching player inserted fixed solenoid pulse durations and didn't need them. I notice in your data the pulse duration can change.

' "Port Recorder - 12 pin v03.bas"
'Reading the 12 outputs of a chiming bells ornament.
'It records the time (mS) when any solenoid is activated/released and which solenoids(s)

Dim integer n, tmr, Port.now, Too.long=8000 'Length of pause that terminates the program (mS)

For n=0 To 11
 SetPin MM.Info(pinno "GP"+Str$(n)),DIN
Next

'GoTo Remap
Open "RecordBells.dat" For Output As #1
Print "  Waiting to start"
Print "Timer",, "Solenoid", "Interval mS"
Timer = 0

Do : Loop Until Port(gp0,12) 'wait for the first pulse
Timer = 100
n=0
Do While Timer-tmr < Too.long
 tmr = Timer
 Do While (Port(gp0,12) = Port.now) And (Timer-tmr < Too.long+50) : Loop 'wait for a solenoid pulse to start/end
 Port.now = Port(gp0,12)
 If (Timer-tmr) < (Too.long-5) Then
   Print #1, Timer; ",", Port.now
   Print Timer, Bin$(Port.now,12), Timer-tmr
  Else
   Print #1, Timer-Too.long+450; ",", 0
   Print Timer-Too.long+450, Bin$(0,12), Timer-tmr
 EndIf
 If (Timer-tmr) > (Too.long-19) Then Exit Do
 Inc n
Loop

Close #1
Print "Finished - more than ";Too.long;"S since last pulse"

'Remap:
'=============================================================================
'Program to re-map the bit positions recorded in RecordBells.dat to Remapped.dat, highest to lowest note
'As per supplied data. If there are errors edit Remap.port(11)=(2,3,1,4,5,0,8,9,7,10,11,6) with 0 - 11 in the correct order.
Print
Print "Remapping solenoids to Remapped.dat"
Open "RecordBells.dat" For Input As #1
Open "Remapped.dat" For Output As #2

'Remapping look-up table
Dim integer Remap.port(11)=(2,3,1,4,5,0,8,9,7,10,11,6) 'highest tone to lowest
'the port() index numbers are the bit positions in the input data and the content is the output bit positions

Dim integer Bell.note.in, Bell.note.out
Dim float Bell.time

Print
Print "Bell.time", "out", "Bell.note.out", "in", "Bell.note.in"
Print

Do
 Input #1, Bell.time, Bell.note.in 'get the data
 Bell.note.out = 0

 For n=0 To 11 'read all the input bit positions and add remapped bits to Bell.note.out
   If (1 << n) = (Bell.note.in And (1 << n)) Then Inc Bell.note.out, (1 << Remap.port(n))
 Next

 Print #2, Bell.time; ",", Bell.note.out
 Print Bell.time, Bell.note.out, Bin$(Bell.note.out,12), Bell.note.in, Bin$(Bell.note.in,12)

Loop Until Eof(#1)

Close #1 : Close #2
End

' "Xylophone player v03.bas"
Dim float SPD=40 'solenoid pulse duration
Dim integer n, Bell.note, Steps=40 'number of on/off transitions in the sequence
Dim float Bell.time, interval

'MakeFile 'Sub to create a test file

For n=0 To 11
 SetPin MM.Info(pinno "GP"+Str$(n)),DOUT
Next

'*******Add your recorded file name here.*************
Open "RecordBells.dat" For Input As #1
'Open "BellSample.dat" For Input As #1

Print "Input time","Solenoid(s)",,"Output time", "interval"

Timer = 0

Do
 Input #1, Bell.time, Bell.note 'get the data
 Do While Timer < Bell.time : Loop 'wait for next note
 Port(gp0,12) = Bell.note 'start / end solenoid pulse
 Print Bell.time, Bin$(Bell.note,12),, Timer, Bell.time-interval
 interval = Bell.time
Loop Until Eof(#1)
Port(gp0,12) = 0

Sub MakeFile
 Open "BellSample.dat" For Output As #1
 For n=0 To Steps\2
   Inc Bell.time, (Rnd * 400 + 100) 'random intervals from 100 to 500mS
   Bell.note = (1 << Fix(Rnd * 12)) Or (1 << Fix(Rnd * 12)) ' ring 2 random bells
   Print #1, Bell.time;","; Bell.note 'solenoid pulse start
   Print Bell.time, Bin$(Bell.note,12)
   Print #1, Bell.time+SPD;","; 0 'solenoid pulse end
   Print Bell.time+SPD, Bin$(0,12)
 Next

 Pause 50
 Print #1, Bell.time+SPD;","; 0 'solenoid pulse end
 Print Bell.time+SPD, Bin$(0,12)
 Close #1
End Sub

End

Edited 2025-11-06 17:05 by phil99
 
Posted: 08:13am
06 Nov 2025
Copy link to clipboard
Frank N. Furter
Guru

Thank you very much, I'll try that tonight.

At the very beginning, all the bells are rung briefly. However, your program only recognizes four of them...

Frank
 
Posted: 11:08am
06 Nov 2025
Copy link to clipboard
Volhout
Guru

@phill99,

Most likely the start of the song is with 12 chimes in a fast sequence (the peak current of actually driving 12 chimes at exactly the same time may be too much for either power supply or ULN2003).

In your loop there is a delay caused by the file print, and screen print. You will capture the first chimes activated, but not all of them. Maybe they are activated in 3 groups of 4.

The best thing to do is open an array, write time and input values in the array, and when you time out (>2 seconds) do a single write to disk. Clear the array, and restart for the next song. Then, at a time out of 8 seconds, stop the sampler.

It is nice to see that they activate the chimes coils 34ms. And (for this song) the beat is (34+198=212ms). Makes it very simple to play back.

Volhout

P.S. -or- you could create a single large array, and capture all songs in one go. It would save memory if you pre-calculate the total time, and leave the 000000 readings out. We already know the chimes are activated for 34ms, and in the new design from Frank, there may be coils that need 50ms, or 60ms. So the total time is all that is needed.
Edited 2025-11-06 21:15 by Volhout
 
Posted: 11:54am
06 Nov 2025
Copy link to clipboard
phil99
Guru


  Quote  You will capture the first chimes activated, but not all of them. Maybe they are activated in 3 groups of 4.
Yes I had come to the same conclusion and have been testing with a modified player simulation that sends 3 groups of 4 (at 1mS intervals) to the recorder. Adding a delay between the the loop that waits for the port to change and reading the port allows all the bits to arrive.

What I don't know is just how long the pause should be before it is too long. More experiments.

I use arrays to capture fast data in other programs and originally intended to in this one but figured the the intervals between notes is so long that I could print directly to a file and the console with time to spare.

This is the output with 3 groups of 4 at 1mS intervals.
Remapping solenoids to Remapped.dat

Bell.time       out     Bell.note.out   in      Bell.note.in

105.389         4095   111111111111     4095   111111111111
771.182         0      000000000000     0      000000000000
807.298         1      000000000001     32     000000100000
1006.049        0      000000000000     0      000000000000
1042.093        2      000000000010     4      000000000100
1240.897        0      000000000000     0      000000000000
1275.902        4      000000000100     1      000000000001
1474.686        0      000000000000     0      000000000000
1509.687        8      000000001000     2      000000000010
1708.442        0      000000000000     0      000000000000
1743.505        16     000000010000     8      000000001000
1942.17         0      000000000000     0      000000000000
1976.144        32     000000100000     16     000000010000
2174.879        0      000000000000     0      000000000000
2208.89         64     000001000000     2048   100000000000
2407.539        0      000000000000     0      000000000000
2470.997        128    000010000000     256    000100000000
2641.326        0      000000000000     0      000000000000
2677.395        256    000100000000     64     000001000000
2876.137        0      000000000000     0      000000000000
2911.086        512    001000000000     128    000010000000
3109.796        0      000000000000     0      000000000000
3143.745        1024   010000000000     512    001000000000
3342.469        0      000000000000     0      000000000000
3377.418        0      000000000000     0      000000000000
3883.177        0      000000000000     0      000000000000
All 8 bits captured and in the right order in the "Bell.note.out" column.

The main loop of the recorder program.
Do : Loop Until Port(gp0,12) 'wait for the first pulse
Timer = 100
n=0
Do While Timer-tmr < Too.long
 tmr = Timer
 Do While (Port(gp0,12) = Port.now) And (Timer-tmr < Too.long+50):Loop 'wait for a solenoid pulse to start/end
 Pause 25 '<================ Add this and adjust to get all 8 bits at the start of the test
 Port.now = Port(gp0,12)
 If (Timer-tmr) < (Too.long-5) Then
   Print #1, Timer; ",", Port.now
   Print Timer, Bin$(Port.now,12), Timer-tmr
  Else
   Print #1, Timer-Too.long+450; ",", 0
   Print Timer-Too.long+450, Bin$(0,12), Timer-tmr
 EndIf
 If (Timer-tmr) > (Too.long-19) Then Exit Do
 Inc n
Loop


In Frank's test data most solenoid pulses are 35mS but one is 63mS. My earlier version omitted all the 0s and supplied fixed length pulses but thought the long pulse might be important so this version captures the pulse lengths as well as the intervals.

Edit.
25mS is about the maximum pause before it goes wonky. If that isn't enough its back to the drawing board.
Pause 25 '<========================== Adjust to get all 8 bits

I expect it will be enough as any longer and Frank would be able to hear the separate groups of bells at the start.
Edited 2025-11-06 22:33 by phil99
 
Posted: 08:02pm
06 Nov 2025
Copy link to clipboard
Frank N. Furter
Guru

Here are the data for the first piece (WITHOUT remapping).

RecordBells.zip

I have taken it up with the latest routine...

Frank
 
Posted: 08:49pm
06 Nov 2025
Copy link to clipboard
phil99
Guru


Scanned through the data and the first chime is still only the first 4 bits.
Have you added the 25mS Pause to the main loop?

Do While (Port(gp0,12) = Port.now) And (Timer-tmr < Too.long+50):Loop 'wait for a solenoid pulse to start/end
Pause 25 '<================ Add this and adjust to get all 8 bits at the start of the test
Port.now = Port(gp0,12)

If you have then then this program may not be the way to go. We need the exact timings of each pin during that first chime of all 12 bells.

In that data most of the pulse lengths are 35mS as before but a few are 26mS In the first sample one was 63mS. I have no idea if that is important or just glitches that don't matter.

To get the remapping you need to let the recording phase timeout, which is now 8 seconds. It then reads back the "RecordBells.dat" file and saves "Remapped.dat".
 
Posted: 09:26pm
06 Nov 2025
Copy link to clipboard
Volhout
Guru

Frank,

You are connecting to the inputs of the ULN2003's ? With 5V logic levels, right ? (at that age the chimes must use 5V logic, not 3.3V).
Are you sure there is a good ground connection between pico and chimes board ?

Volhout
Edited 2025-11-07 07:30 by Volhout
 
Posted: 10:07pm
06 Nov 2025
Copy link to clipboard
phil99
Guru


Here is a short program to capture the first 100mS of your first test, all 12 bells then one at a time.
Could you please post the output from TeraTerm.
Dim integer samples=2000
Dim GetData(samples%,2)
Print " Waiting to start"
Print "Timer", "Port", "Binary",,"interval uS"
Timer = 0

Do : Loop Until Port(gp0,12):tmr=Timer 'wait for the first pulse
For n=0 To samples :GetData(n,0)=Port(gp0,12):GetData(n,1)=Timer-tmr:Next

For n=0 To samples-1
 Print GetData(n,1),GetData(n,0),Bin$(GetData(n,0),12),cint((GetData(n+1,1)-GetData(n,1))*1000)
Next

End

And here is what I am testing on.
> option list
PicoMiteVGA MMBasic RP2040 Edition V6.01.00RC10
OPTION COLOURCODE ON
OPTION RESOLUTION 640x480 @ 252000KHz
OPTION DISPLAY 55, 133
>

Edited 2025-11-07 10:26 by phil99
 
Posted: 07:29am
07 Nov 2025
Copy link to clipboard
Frank N. Furter
Guru

@phill99:

I recorded it with your new “MAIN LOOP”.

@Volhout:

Yes, the inputs operate at 5V. I have built 12 voltage dividers (10k/10k) on a circuit board and soldered GND via a separate wire.


I'll try out the new test program from Phill later and let you know the results...

Frank
 
Posted: 07:40am
07 Nov 2025
Copy link to clipboard
Volhout
Guru

Hi Frank,

1/ are you using a RP2350 (pico2) or a RP2040 (pico). The pico2 may still suffer from the GPIO bug (hardware bug). Bu I have no idea how this could influence the reading of only these 4 bits specific.

2/ 10k/22k would be more suitable to achieve 3.3V from 5V. A 10k/10k has a theoretical maximum high level of 2.5V. The ULN2003 loads the IO pin of the microchip, so the voltage may only be 4.5V best case. In case the 5V voltage drops with multiple chimes active at the same time, you may not get the required 2V needed for the pico.

Volhout
Edited 2025-11-07 17:40 by Volhout
 
Posted: 07:43am
07 Nov 2025
Copy link to clipboard
phil99
Guru


Just noticed a typo in the last test program.
Here it is again.
Dim integer samples=2000
Dim GetData(samples,2)
Print " Waiting to start"
Print "Timer", "Port", "Binary",,"interval uS"
Timer = 0

Do : Loop Until Port(gp0,12):tmr=Timer 'wait for the first pulse
For n=0 To samples :GetData(n,0)=Port(gp0,12):GetData(n,1)=Timer-tmr:Next

For n=0 To samples-1
 Print GetData(n,1),GetData(n,0),Bin$(GetData(n,0),12),cint((GetData(n+1,1)-GetData(n,1))*1000)
Next
End


On the RP2040 @252MHz the above program sample interval is 60 to 70µS, which should be enough to see any important timing issues. Reducing the variables to one letter got it below 50µS.

You could be on to something there. Looking at the photo in the first post it looks like it is powered from a plug-pack so there could be voltage drop there too as the capacitors loose charge with the peak load, adding to what you mentioned.
Edited 2025-11-07 17:59 by phil99
 
Posted: 08:48am
07 Nov 2025
Copy link to clipboard
Mixtel90
Guru


You have to assume that, on a 5V system, you will rarely get as much as 4V across the load if driven by a ULN2003.

It's not a great driver chip unless your coil voltages are above 9V IMHO. The Vce(sat) of the output transistors is poor (it can be between 0.9V @ 100mA and 1.6V @ 350mA) and the package power dissipation is limited by how many outputs you can drive into full saturation. I much prefer discrete mosfets, each with a pull-down resistor. Easier to drive and much lower on resistance.
 
Posted: 10:29am
07 Nov 2025
Copy link to clipboard
Volhout
Guru

Mick,

Frank measures at the ULN2003 INPUT pins.

Volhout
 
Posted: 01:07pm
07 Nov 2025
Copy link to clipboard
Frank N. Furter
Guru

Yes, the circuit is powered by an unregulated 12V plug-in power supply. The required 5V is generated on the circuit board using a Zener diode – I measured 5.3V.







BUT SORRY, I said something wrong!  

At the beginning, NOT ALL bells are rung. Only FOUR are rung—I always thought it was all of them... SORRY!!!


It's the four pieces at the bottom right that form a square. Sorry again!  

Frank
 
   Page 2 of 5    
The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025