I want make a one second timer with atmega8 and timer0. I used 8Mhz crystal and prescale = 1.
Every 125ns timer0 increases by one, so when timer0 overflows 31250 times, we should have one second, but it doesn't work properly and delays more then 5 seconds.
I used BascomAVR.
$regfile = "m8def.dat"
$crystal = 8000000
Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6
,Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2
Config Timer0 = Timer , Prescale = 1
Dim Second As Word , Minute As Word , Hour As Word , Z As Integer
Second = 0
Minute = 0
Hour = 0
Z = 0
Enable Interrupts
Enable Timer0
Enable Ovf0
On Ovf0 Ovfroutin
Timer0 = 0
Start Timer0
Cursor Off
Cls : Home
Lcd "00:00:00"
Do
Loop
End 'end program
Ovfroutin:
Incr Z
If Z = 31250 Then
Stop Timer0
Z = 0
Incr Second
If Second = 60 Then
Second = 0
Incr Minute
If Minute = 60 Then
Minute = 0
Incr Hour
If Hour = 24 Then
Hour = 0
End If
If Hour < 10 Then
Locate 1 , 1
Lcd "0"
Locate 1 , 2
Else
Locate 1 , 1
End If
Lcd Hour
End If
If Minute < 10 Then
Locate 1 , 4
Lcd "0"
Locate 1 , 5
Else
Locate 1 , 4
End If
Lcd Minute
End If
If Second < 10 Then
Locate 1 , 7
Lcd "0"
Locate 1 , 8
Else
Locate 1 , 7
End If
Lcd Second
Start Timer0
End If
Timer0 = 0
Return
Related
How to count from 0 to 99 using two 7SEG-BCD in proteus. I also tried to shift bits but i didn't succeed.
$regfile="m32def.dat"
$crystal=8000000
config portc = output
dim a as byte,b as byte
do
for a = 0 to 9
for b = 0 to 9
portc = makeint(a, b)
waitms 100
next
next
loop
end
I have a 1 by 1000 (1 row by 1000 columns) matrix that contain only 0 and 1 as their elements. How can I find how many times 1 is repeated 3 times consecutively.
If there are more than 3 ones then it is necessary to reset the counting. So 4 would be 3+1 and it counts as only one instance of 3 consecutive 1s but 6 would be 3+3 so it counts as two instances of having 3 consecutive 1s.
This approach finds the differences between when A goes from 0 to 1 (rising edge) and from 1 to 0 (falling edge). This gives the lengths of consecutive 1s in each block. Then divide these numbers by 3 and round down to get the number of runs of 3.
Padding A with a 0 at the start and end just ensures we have a rising edge at the start if A starts with a 1, and we have a falling edge at the end if A ends with a 1.
A = round(rand(1,1000));
% padding with a 0 at the start and end will make this simpler
B = [0,A,0];
rising_edges = ~B(1:end-1) & B(2:end);
falling_edges = B(1:end-1) & ~B(2:end);
lengths_of_ones = find(falling_edges) - find(rising_edges);
N = sum(floor(lengths_of_ones / 3));
Or in a much less readable 2 lines:
A = round(rand(1,1000));
B = [0,A,0];
N = sum(floor((find(B(1:end-1) & ~B(2:end)) - find(~B(1:end-1) & B(2:end))) / 3));
You can define your custom functions like below
v = randi([0,1],1,1000);
% get runs in cell array
function C = runs(v)
C{1} = v(1);
for k = 2:length(v)
if v(k) == C{end}(end)
C{end} = [C{end},v(k)];
else
C{end+1} = v(k);
end
end
end
% count times of 3 consecutive 1s
function y = count(x)
if all(x)
y = floor(length(x)/3);
else
y = 0;
end
end
sum(cellfun(#count,runs(v)))
Here is another vectorized way:
% input
n = 3;
a = [1 1 1 1 0 0 1 1 1 0 0 0 1 1 1 1 1 0 1 1 1 1 1 1 1]
% x x x x x = 5
% output
a0 = [a 0];
b = cumsum( a0 ) % cumsum
c = diff( [0 b( ~( diff(a0) + 1 ) ) ] ) % number of ones within group
countsOf3 = sum( floor( c/n ) ) % groups of 3
You like it messy? Here is a one-liner:
countsOf3 = sum(floor(diff([0 getfield(cumsum([a 0]),{~(diff([a 0])+1)})])/n))
I am trying to use the Altera DE0-nano to communication with the PC. I am using the ttl-232R-3v3 cable, currently it transmit 8 bits data once, but with the cable, it can be 1 bit a time transmit. How do I do it?
I have finish the 8 bit code:
type ST = BitVector 28
example :: ( ST , ST ) -> BitVector 8 -> (( ST , ST ) , BitVector 8)
example ( cntr1 , cntr2 ) input = ((cntr1’,cntr2’) , out)
where
sec_5 = 250000000
ascii_Y = 0x59 --ASCII for "Y" yes
ascii_N = 0x4E --ASCII for "N" no
cntr1’ | cntr1 >= sec_5 = 0 --At 50 MHz : 5 seconds
| otherwise = cntr1 + 1
cntr2’ = cntr2
out | input == maxBound = ascii_Y
| otherwise = ascii_Y
Here is the output:
I have an array with some durations (in seconds), I'd like to split that array into accumulated duration groups that not surpass 3600 seconds in MATLAB. The durations are in order.
Input:
Duration(s) | 2010 1000 500 1030 80 2030 1090
With an:
------------- ------------ ----
Accumulated duration (s) | 3510 3130 1090
------------- ------------ ----
1st group 2nd group 3rd
Output:
Groups index | 1 1 1 2 2 2 3
I've tried with some scripts, but these take so long, and I have to process a lot of data.
Here is a vectorized way using bsxfun and cumsum:
durations = [2010 1000 500 1030 80 2030 1090]
stepsize = 3600;
idx = sum(bsxfun(#ge, cumsum(durations), (0:stepsize:sum(durations)).'),1)
idx =
1 1 1 2 2 2 3
The accumulated durations you can then get with:
accDuratiation = accumarray(idx(:),durations(:),[],#sum).'
accDuratiation =
3510 3140 1090
Explanation:
%// cumulative sum of all durations
csum = cumsum(durations);
%// thresholds
threshs = 0:stepsize:sum(durations);
%// comparison
comp = bsxfun(#ge, csum(:).',threshs(:)) %'
comp =
1 1 1 1 1 1 1
0 0 0 1 1 1 1
0 0 0 0 0 0 1
%// get index
idx = sum(comp,1)
This will get you close . . .
durs = [2010 1000 500 1030 80 2030 1090];
cums = cumsum(durs);
t = 3600;
idx = zeros(size(durs));
while ~all(idx)
idx = idx + (cums <= t);
cums = cums - max(cums(cums <= t));
end
You can then get the output into your preferred format with a simple . .
idx = -(idx-max(idx)-1)
and just in case you don't have enough, yet another way to do it:
durations = [2010 1000 500 1030 80 2030 1090] ;
stepsize = 3600;
cs = cumsum(durations) ;
idxbeg = [1 find(sign([1 diff(mod(cs,stepsize))])==-1)] ; %// first index of each group
idxend = [idxbeg(2:end)-1 numel(d)] ; %// last index of each group
groupDuration = [cs(idxend(1)) diff(cs(idxend))]
groupIndex = cell2mat( arrayfun(#(x,y) repmat(x,1,y), 1:numel(idxbeg) , idxend-idxbeg+1 , 'uni',0) )
groupDuration =
3510 3140 1090
groupIndex =
1 1 1 2 2 2 3
although if you ask me I find the bsxfun solution more elegant
I need to find the longest interval of 1's in a matrix, and the position of the first "1" in that interval.
For example if i have a matrix: [1 0 0 1 1 1 0 0 0 0 1 1 1 1 1 1 1 ]
I need to have both the length of 7 and that the first 1's position is 11.
Any suggestions on how to proceed would be appreciated.
Using this anwser as a basis, you can do as follows:
a = [1 0 0 1 1 1 0 0 0 0 1 1 1 1 1 1 1 ]
dsig = diff([0 a 0]);
startIndex = find(dsig > 0);
endIndex = find(dsig < 0) - 1;
duration = endIndex-startIndex+1;
duration
startIdx = startIndex(duration == max(duration))
endIdx = endIndex(duration == max(duration))
This outputs:
duration =
1 3 7
startIdx =
11
endIdx =
17
Please note, this probably needs double checking if it works for other cases than your example. Nevertheless, I think this is the way in the right directions. If not, in the linked anwser you can find more info and possibilities.
If there are multiple intervals of one of the same length, it will only give the position of the first interval.
A=round(rand(1,20)) %// test vector
[~,p2]=find(diff([0 A])==1); %// finds where a string of 1's starts
[~,p3]=find(diff([A 0])==-1); %// finds where a string of 1's ends
le=p3-p2+1; %// length of each interval of 1's
ML=max(le); %// length of longest interval
ML %// display ML
p2(le==ML) %// find where strings of maximum length begin (per Marcin's answer)
I have thought of a brute force approach;
clc; clear all; close all;
A= [1 0 0 1 1 1 0 0 0 0 1 1 1 1 1 1 1 ];
index = 1;
globalCount = 0;
count = 0;
flag = 0; %// A flag to keep if the previous encounter was 0 or 1
for i = 1 : length(A)
if A(i) == 1
count = count + 1;
if flag == 0
index = i
flag = 1;
end
end
if A(i) == 0 || i == length(A)
if count > globalCount
globalCount = count;
end
flag = 0;
count = 0;
end
end