| Menu | JAQForum Ver 19.10.27 |
Forum Index : Microcontroller and PC projects : read out carolling christmas bells
@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... |
||||||
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) |
||||||
PORT(GP0,12) ? Volhout |
||||||
Yes, the Port Function behaves differently to the Port Command. It works so I wont complain! |
||||||
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 |
||||||
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 |
||||||
The recording program now has a re-ordering program tacked on the end that uses your recorded data for the translation. 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 > 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 "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 "Bell.time", "out", "Bell.note.out", "in", "Bell.note.in" 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 |
||||||
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 |
||||||
@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 |
||||||
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 All 8 bits captured and in the right order in the "Bell.note.out" column.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 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 |
||||||
Here are the data for the first piece (WITHOUT remapping). RecordBells.zip I have taken it up with the latest routine... Frank |
||||||
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". |
||||||
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 |
||||||
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 |
||||||
@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 |
||||||
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 |
||||||
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 |
||||||
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. |
||||||
Mick, Frank measures at the ULN2003 INPUT pins. Volhout |
||||||
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 |
||||||
| The Back Shed's forum code is written, and hosted, in Australia. |