STM32F4 PWM ramp - interrupt

I'm working on a project where I want to ramp the pwm duty cycle from 0 to 50%. My period is 16000 counts or 1ms (16MHz default timer count). For some reason, instead of updating the duty cycle each period, it updates it much slower. I wonder if it's because I'm calculating the new duty cycle within the timer interrupt? Here's what I'm using:
void TIM4_IRQHandler()
{
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
if (loop <= 8000) {
TIM4 -> CCR1 = CCR_i;
uint16_t y = CCR_i;
CCR_i = y + 1;
int x = loop;
loop = x + 1;
}
if (loop == 8001) {
TIM4 -> CCR1 = 0;
uint16_t x = CCR_i;
CCR_i = x + 1;
int c = loop;
loop = c + 1;
}
if (loop > 8001) {
int t;
for(t = 0; t < 10; t++){
// wait
}
GPIO_SetBits(GPIOG, GPIO_Pin_8);
//Stop2();
TIM_ITConfig(TIM4, TIM_IT_Update, DISABLE);
NVIC_DisableIRQ(TIM4_IRQn);
}
}
}

blast, it looks like I was being silly - the timer is doing exactly what I want it to - it just takes 8 seconds with a period of 1ms to ramp to a pulsewidth of 500us adding 62.5ns per period.

Related

BME680 sensor faulty gas reference readings

I have a problem with my BME680 readings. I found example code to collect all the air data and make an air quality score (AIQ) out of that (it goes from 0 to 500). You see in the code bellow that in loop() data is collected and AIQ calculated every 2 seconds, and gas reference is updated/collected on every 5-th reading -> if (getgasreference_count++) % 5 == 0) GetGasReference(); so 5*2 sec= every 10 sec (around 230k ohms).
Problem starts here, where I implement this code in my other program which runs website and controls motors. Here data is collected and AIQ calculated once a minute, gas reference is updated/collected on every 5-th reading -> if (getgasreference_count++) % 5 == 0) GetGasReference(); so 5*60 sec= every 300 sec= 5 min. Thats when I'm getting faulty gas reference readings (around 100k ohms) and of course following calculated AIQ is wrong.
I'm wondering where the problem is because why it matters when you get new gas reference? I'm thinking that bme.setGasHeater(); function has something to do with it, but I don't know how it is related with gas reference readings? I would be grateful if anybody can explain where the problem is.
The working example code is here:
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME680.h>
#define SEALEVELPRESSURE_HPA (1013.25)
#define YOUR_SENSOR_I2C_ADDRESS 0x76
Adafruit_BME680 bme; // I2C
float hum_weighting = 0.25; // so hum effect is 25% of the total air quality score
float gas_weighting = 0.75; // so gas effect is 75% of the total air quality score
int humidity_score, gas_score;
float gas_reference = 2500;
float hum_reference = 40;
int getgasreference_count = 0;
int gas_lower_limit = 10000; // Bad air quality limit
int gas_upper_limit = 300000; // Good air quality limit
void setup() {
Serial.begin(115200);
Serial.println(F("BME680 test"));
Wire.begin();
if (!bme.begin(YOUR_SENSOR_I2C_ADDRESS)) {
Serial.println("Could not find a valid BME680 sensor, check wiring!");
while (1);
} else Serial.println("Found a sensor");
// Set up oversampling and filter initialization
bme.setTemperatureOversampling(BME680_OS_8X);
bme.setHumidityOversampling(BME680_OS_2X);
bme.setPressureOversampling(BME680_OS_4X);
bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
bme.setGasHeater(320, 150); // 320°C for 150 ms
// Now run the sensor to normalise the readings, then use combination of relative humidity and gas resistance to estimate indoor air quality as a percentage.
// The sensor takes ~30-mins to fully stabilise
GetGasReference();
}
void loop() {
Serial.println("Sensor Readings:");
Serial.println(" Temperature = " + String(bme.readTemperature(), 2) + "°C");
Serial.println(" Pressure = " + String(bme.readPressure() / 100.0F) + " hPa");
Serial.println(" Humidity = " + String(bme.readHumidity(), 1) + "%");
Serial.println(" Gas = " + String(gas_reference) + " ohms\n");
Serial.print("Qualitative Air Quality Index ");
humidity_score = GetHumidityScore();
gas_score = GetGasScore();
//Combine results for the final IAQ index value (0-100% where 100% is good quality air)
float air_quality_score = humidity_score + gas_score;
Serial.println(" comprised of " + String(humidity_score) + "% Humidity and " + String(gas_score) + "% Gas");
if ((getgasreference_count++) % 5 == 0) GetGasReference();
Serial.println(CalculateIAQ(air_quality_score));
Serial.println("--------------------------------------------------------------");
delay(2000);
}
void GetGasReference() {
// Now run the sensor for a burn-in period, then use combination of relative humidity and gas resistance to estimate indoor air quality as a percentage.
//Serial.println("Getting a new gas reference value");
int readings = 10;
for (int i = 1; i <= readings; i++) { // read gas for 10 x 0.150mS = 1.5secs
gas_reference += bme.readGas();
}
gas_reference = gas_reference / readings;
//Serial.println("Gas Reference = "+String(gas_reference,3));
}
String CalculateIAQ(int score) {
String IAQ_text = "air quality is ";
score = (100 - score) * 5;
if (score >= 301) IAQ_text += "Hazardous";
else if (score >= 201 && score <= 300 ) IAQ_text += "Very Unhealthy";
else if (score >= 176 && score <= 200 ) IAQ_text += "Unhealthy";
else if (score >= 151 && score <= 175 ) IAQ_text += "Unhealthy for Sensitive Groups";
else if (score >= 51 && score <= 150 ) IAQ_text += "Moderate";
else if (score >= 00 && score <= 50 ) IAQ_text += "Good";
Serial.print("IAQ Score = " + String(score) + ", ");
return IAQ_text;
}
int GetHumidityScore() { //Calculate humidity contribution to IAQ index
float current_humidity = bme.readHumidity();
if (current_humidity >= 38 && current_humidity <= 42) // Humidity +/-5% around optimum
humidity_score = 0.25 * 100;
else
{ // Humidity is sub-optimal
if (current_humidity < 38)
humidity_score = 0.25 / hum_reference * current_humidity * 100;
else
{
humidity_score = ((-0.25 / (100 - hum_reference) * current_humidity) + 0.416666) * 100;
}
}
return humidity_score;
}
int GetGasScore() {
//Calculate gas contribution to IAQ index
gas_score = (0.75 / (gas_upper_limit - gas_lower_limit) * gas_reference - (gas_lower_limit * (0.75 / (gas_upper_limit - gas_lower_limit)))) * 100.00;
if (gas_score > 75) gas_score = 75; // Sometimes gas readings can go outside of expected scale maximum
if (gas_score < 0) gas_score = 0; // Sometimes gas readings can go outside of expected scale minimum
return gas_score;
}
From this Learn Adafruit page it seems the gas readouts can take up to 30 minutes to stabilize.
Gas is returned as a resistance value in ohms. This value takes up to 30 minutes to stabilize! Once it stabilizes, you can use that as your baseline reading. Higher concentrations of VOC will make the resistance lower.
and on their first page:
We recommend that you run this sensor for 48 hours when you first receive it to "burn it in", and then 30 minutes in the desired mode every time the sensor is in use.

How to stop the search in CP Optimizer if the upper bound doesn't get better after x seconds

I'm wondering if there exists a way in CP Optimizer 12.10 to stop the search if the upper bound (of a minimization problem) doesn't get better after "x" seconds. This would be especially helpful when trying to solve a difficult instance of an NP-Hard problem and the search is stuck in one incumbent solution.
I know there exist some parameters to control the search as cp.param.TimeLimit (I'm using that) or cp.param.FailLimit but that is not that I need for my problem.
Any help would be highly appreciated.
what you can do is use a main block (flow control) if you rely on the OPL API and in this main block you give a time limit of x seconds, then you get the bound and the current objective, you save them if you think you should go further or stop if you're ok with the solution.
Let me share a full example out of the lifegame example in the OPL product. And remember John Conway once again.
using CP;
int n=20;
int Half=n div 2;
range FirstHalf = 1..Half;
range LastHalf = n-Half+1..n;
range States = 0..1;
range Bord = 0..(n+1);
range Interior = 1..n;
range obj = 0..(n*n);
tuple neighbors {
int row;
int col;
}
{neighbors} Neighbor =
{<(-1),(-1)>,<(-1),0>,<(-1),1>,<0,(-1)>,<0,1>,<1,(-1)>,<1,0>,<1,1>};
dvar int Life[Bord][Bord] in States;
dvar int Obj in obj;
dvar int x[0..(n+2)*(n+2)-1];
maximize Obj;
subject to {
forall(i,j in Bord) Life[i][j]==x[i*(n+2)+j];
//ct1:
Obj == sum( i , j in Bord )
Life[i][j];
forall( i , j in Interior ) {
ct21:
2*Life[i][j] - sum( nb in Neighbor )
Life[i+nb.row][j+nb.col] <= 0;
ct22:
3*Life[i][j] + sum( nb in Neighbor )
Life[i+nb.row][j+nb.col] <= 6;
forall( ordered n1 , n2 , n3 in Neighbor ) {
ct23:
-Life[i][j]+Life[i+n1.row][j+n1.col]
+Life[i+n2.row][j+n2.col]
+Life[i+n3.row][j+n3.col]
-sum( nb in Neighbor : nb!=n1 && nb!=n2 && nb!=n3 )
Life[i+nb.row][j+nb.col] <= 2;
}
}
forall( j in Bord ) {
ct31:
Life[0][j] == 0;
ct32:
Life[j][0] == 0;
ct33:
Life[j][n+1] == 0;
ct34:
Life[n+1][j] == 0;
}
forall( i in Bord : i<n ) {
ct41:
Life[i][1]+Life[i+1][1]+Life[i+2][1] <= 2;
ct42:
Life[1][i]+Life[1][i+1]+Life[1][i+2] <= 2;
ct43:
Life[i][n]+Life[i+1][n]+Life[i+2][n] <= 2;
ct44:
Life[n][i]+Life[n][i+1]+Life[n][i+2] <= 2;
}
ct5:
sum( i in FirstHalf , j in Bord )
Life[i][j] >=
sum( i in LastHalf , j in Bord )
Life[i][j];
ct6:
sum( i in Bord , j in FirstHalf )
Life[i][j] >=
sum( i in Bord , j in LastHalf )
Life[i][j];
}
main
{
thisOplModel.generate();
cp.param.timelimit=10;
var obj=0;
var bound=0;
var oldobj=0;
var oldbound=0;
while (1==1)
{
cp.solve();
obj=cp.getObjValue();
bound=cp.getObjBound();
writeln("bound and obj =",bound," ",obj);
if (Opl.abs((oldobj-oldbound-obj+bound))<=0) break;
oldobj=obj;
oldbound=bound;
}
}
which gives
bound and obj =398 181
bound and obj =398 180
bound and obj =398 180
// Script execution finished with status 1.

Why is my nested while loop not working?

I'm currently programming in RobotC, for a Vex 2.0 Cortex. I'm using encoders to make my robot go straight.
This is my code:
void goforwards(int time)
{
int Tcount = 0;
int speed1 = 40;
int speed2 = 40;
int difference = 10;
motor[LM] = speed1;
motor[RM] = speed2;
while (Tcount < time)
{
nMotorEncoder[RM] = 0;
nMotorEncoder[LM] = 0;
while(nMotorEncoder[RM]<1000)
{
int REncoder = -nMotorEncoder[RM];
int LEncoder = -nMotorEncoder[LM];
if (LEncoder > REncoder)
{
motor[LM] = speed1 - difference;
motor[RM] = speed2 + difference;
if (motor[RM]<= 0)
{
motor[RM] = 40;
motor[LM] = 40;
}
}
if (LEncoder < REncoder)
{
motor[LM] = speed1 + difference;
motor[RM] = speed2 - difference;
if (motor[RM]<= 0)
{
motor[RM] = 40;
motor[LM] = 40;
}
Tcount ++;
}
}
}
}
task main()
{
goforwards(10);
}
For reference, these are my Pragma settings:
#pragma config(I2C_Usage, I2C1, i2cSensors)
#pragma config(Sensor, dgtl2, , sensorDigitalIn)
#pragma config(Sensor, dgtl7, , sensorDigitalOut)
#pragma config(Sensor, I2C_1, , sensorQuadEncoderOnI2CPort, , AutoAssign )
#pragma config(Sensor, I2C_2, , sensorQuadEncoderOnI2CPort, , AutoAssign )
#pragma config(Motor, port1, RM, tmotorVex393_HBridge, openLoop, reversed, encoderPort, I2C_2)
#pragma config(Motor, port10, LM, tmotorVex393_HBridge, openLoop, encoderPort, I2C_1)
When I excecute the code, the Robot's encoder values are very close, but the robot stops moving when they reach 1000. I thought the code I wrote should return the values of the encoders back to 0 after they reach 1 thousand, and thereby the code should re-iterate in the shell loop 10 times (in this case). What have I done wrong?
You are updating Tcount at the wrong place. Do it Just at the end of the outer loop.
What you have written now makes Tcount increase everytime it moves ahead. By the time it reaches 1000 steps, Tcount is already 1000.
Your times is 10. So `Tcount >= time and it wont enter the outer while loop again.
It seems that the Control Variable of the inner loop (i.e. nMotorEncoder[RM]) is never updated, this means that the inner loop will iterate forever. That is, you will never go back to the body of external loop

Issues in ADC of PIC16F887 reading LM35 temperature value is frequently varying

I have connected the LM35 temperature sensor in analog channel of AN1 then transmitting the temperature through serial RS232 in PIC16F887. I have read the temperature value but the value is frequently varying as 31 and 32, also when touch the LM35 temperature is varying very fast as 32, 33 and etc. How to control the constant temperature value. Here is my code, Please any one help me.
#include <htc.h>
void main(void)
{
TRISA1 = 1;
ANS1 = 1;
OSCCON = 0x78; // OSCILLATOR CONTROL REGISTER
TXSTA = 0x26;
RCSTA = 0x90;
SPBRG = 10;
ADCON1 = 0x80;
unsigned int current_temp, initial_temp = temperature();
transmit_char(initial_temp);
flag = 0;
while (1)
{
current_temp = temperature();
if((current_temp == (initial_temp + 1)) || (current_temp == (initial_temp - 1)))
{
flag = 1;
}
if(flag == 1)
{
flag = 0;
transmit_char(current_temp);
initial_temp = current_temp;
}
}
}
int temperature(void)
{
ADCON0 = 0xC5;
GODONE = 1;
while(GODONE);
int temp;
temp = (ADRESH << 8) + ADRESL;
temp = temp/2;
return temp;
}
Do this,
Collect ten adc data,
Remove min and max from that values.
sum the remaining 8 ADC values and divide the value by 8.
this should be continuous process, average for every ten samples
note: sampling and averaging should be ... 1 to 10 , next 2 to 11 and 3 to 12. at every reading you will get the adc value. sudden fluctuations also get filtered here.
Hope this helps.. good luck..

When can an algorithm have square root(n) time complexity?

Can someone give me example of an algorithm that has square root(n) time complexity. What does square root time complexity even mean?
Square root time complexity means that the algorithm requires O(N^(1/2)) evaluations where the size of input is N.
As an example for an algorithm which takes O(sqrt(n)) time, Grover's algorithm is one which takes that much time. Grover's algorithm is a quantum algorithm for searching an unsorted database of n entries in O(sqrt(n)) time.
Let us take an example to understand how can we arrive at O(sqrt(N)) runtime complexity, given a problem. This is going to be elaborate, but is interesting to understand. (The following example, in the context for answering this question, is taken from Coding Contest Byte: The Square Root Trick , very interesting problem and interesting trick to arrive at O(sqrt(n)) complexity)
Given A, containing an n elements array, implement a data structure for point updates and range sum queries.
update(i, x)-> A[i] := x (Point Updates Query)
query(lo, hi)-> returns A[lo] + A[lo+1] + .. + A[hi]. (Range Sum Query)
The naive solution uses an array. It takes O(1) time for an update (array-index access) and O(hi - lo) = O(n) for the range sum (iterating from start index to end index and adding up).
A more efficient solution splits the array into length k slices and stores the slice sums in an array S.
The update takes constant time, because we have to update the value for A and the value for the corresponding S. In update(6, 5) we have to change A[6] to 5 which results in changing the value of S1 to keep S up to date.
The range-sum query is interesting. The elements of the first and last slice (partially contained in the queried range) have to be traversed one by one, but for slices completely contained in our range we can use the values in S directly and get a performance boost.
In query(2, 14) we get,
query(2, 14) = A[2] + A[3]+ (A[4] + A[5] + A[6] + A[7]) + (A[8] + A[9] + A[10] + A[11]) + A[12] + A[13] + A[14] ;
query(2, 14) = A[2] + A[3] + S[1] + S[2] + A[12] + A[13] + A[14] ;
query(2, 14) = 0 + 7 + 11 + 9 + 5 + 2 + 0;
query(2, 14) = 34;
The code for update and query is:
def update(S, A, i, k, x):
S[i/k] = S[i/k] - A[i] + x
A[i] = x
def query(S, A, lo, hi, k):
s = 0
i = lo
//Section 1 (Getting sum from Array A itself, starting part)
while (i + 1) % k != 0 and i <= hi:
s += A[i]
i += 1
//Section 2 (Getting sum from Slices directly, intermediary part)
while i + k <= hi:
s += S[i/k]
i += k
//Section 3 (Getting sum from Array A itself, ending part)
while i <= hi:
s += A[i]
i += 1
return s
Let us now determine the complexity.
Each query takes on average
Section 1 takes k/2 time on average. (you might iterate atmost k/2)
Section 2 takes n/k time on average, basically number of slices
Section 3 takes k/2 time on average. (you might iterate atmost k/2)
So, totally, we get k/2 + n/k + k/2 = k + n/k time.
And, this is minimized for k = sqrt(n). sqrt(n) + n/sqrt(n) = 2*sqrt(n)
So we get a O(sqrt(n)) time complexity query.
Prime numbers
As mentioned in some other answers, some basic things related to prime numbers take O(sqrt(n)) time:
Find number of divisors
Find sum of divisors
Find Euler's totient
Below I mention two advanced algorithms which also bear sqrt(n) term in their complexity.
MO's Algorithm
try this problem: Powerful array
My solution:
#include <bits/stdc++.h>
using namespace std;
const int N = 1E6 + 10, k = 500;
struct node {
int l, r, id;
bool operator<(const node &a) {
if(l / k == a.l / k) return r < a.r;
else return l < a.l;
}
} q[N];
long long a[N], cnt[N], ans[N], cur_count;
void add(int pos) {
cur_count += a[pos] * cnt[a[pos]];
++cnt[a[pos]];
cur_count += a[pos] * cnt[a[pos]];
}
void rm(int pos) {
cur_count -= a[pos] * cnt[a[pos]];
--cnt[a[pos]];
cur_count -= a[pos] * cnt[a[pos]];
}
int main() {
int n, t;
cin >> n >> t;
for(int i = 1; i <= n; i++) {
cin >> a[i];
}
for(int i = 0; i < t; i++) {
cin >> q[i].l >> q[i].r;
q[i].id = i;
}
sort(q, q + t);
memset(cnt, 0, sizeof(cnt));
memset(ans, 0, sizeof(ans));
int curl(0), curr(0), l, r;
for(int i = 0; i < t; i++) {
l = q[i].l;
r = q[i].r;
/* This part takes O(n * sqrt(n)) time */
while(curl < l)
rm(curl++);
while(curl > l)
add(--curl);
while(curr > r)
rm(curr--);
while(curr < r)
add(++curr);
ans[q[i].id] = cur_count;
}
for(int i = 0; i < t; i++) {
cout << ans[i] << '\n';
}
return 0;
}
Query Buffering
try this problem: Queries on a Tree
My solution:
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10, k = 333;
vector<int> t[N], ht;
int tm_, h[N], st[N], nd[N];
inline int hei(int v, int p) {
for(int ch: t[v]) {
if(ch != p) {
h[ch] = h[v] + 1;
hei(ch, v);
}
}
}
inline void tour(int v, int p) {
st[v] = tm_++;
ht.push_back(h[v]);
for(int ch: t[v]) {
if(ch != p) {
tour(ch, v);
}
}
ht.push_back(h[v]);
nd[v] = tm_++;
}
int n, tc[N];
vector<int> loc[N];
long long balance[N];
vector<pair<long long,long long>> buf;
inline long long cbal(int v, int p) {
long long ans = balance[h[v]];
for(int ch: t[v]) {
if(ch != p) {
ans += cbal(ch, v);
}
}
tc[v] += ans;
return ans;
}
inline void bal() {
memset(balance, 0, sizeof(balance));
for(auto arg: buf) {
balance[arg.first] += arg.second;
}
buf.clear();
cbal(1,1);
}
int main() {
int q;
cin >> n >> q;
for(int i = 1; i < n; i++) {
int x, y; cin >> x >> y;
t[x].push_back(y); t[y].push_back(x);
}
hei(1,1);
tour(1,1);
for(int i = 0; i < ht.size(); i++) {
loc[ht[i]].push_back(i);
}
vector<int>::iterator lo, hi;
int x, y, type;
for(int i = 0; i < q; i++) {
cin >> type;
if(type == 1) {
cin >> x >> y;
buf.push_back(make_pair(x,y));
}
else if(type == 2) {
cin >> x;
long long ans(0);
for(auto arg: buf) {
hi = upper_bound(loc[arg.first].begin(), loc[arg.first].end(), nd[x]);
lo = lower_bound(loc[arg.first].begin(), loc[arg.first].end(), st[x]);
ans += arg.second * (hi - lo);
}
cout << tc[x] + ans/2 << '\n';
}
else assert(0);
if(i % k == 0) bal();
}
}
There are many cases.
These are the few problems which can be solved in root(n) complexity [better may be possible also].
Find if a number is prime or not.
Grover's Algorithm: allows search (in quantum context) on unsorted input in time proportional to the square root of the size of the input.link
Factorization of the number.
There are many problems that you will face which will demand use of sqrt(n) complexity algorithm.
As an answer to second part:
sqrt(n) complexity means if the input size to your algorithm is n then there approximately sqrt(n) basic operations ( like **comparison** in case of sorting). Then we can say that the algorithm has sqrt(n) time complexity.
Let's analyze the 3rd problem and it will be clear.
let's n= positive integer. Now there exists 2 positive integer x and y such that
x*y=n;
Now we know that whatever be the value of x and y one of them will be less than sqrt(n). As if both are greater than sqrt(n)
x>sqrt(n) y>sqrt(n) then x*y>sqrt(n)*sqrt(n) => n>n--->contradiction.
So if we check 2 to sqrt(n) then we will have all the factors considered ( 1 and n are trivial factors).
Code snippet:
int n;
cin>>n;
print 1,n;
for(int i=2;i<=sqrt(n);i++) // or for(int i=2;i*i<=n;i++)
if((n%i)==0)
cout<<i<<" ";
Note: You might think that not considering the duplicate we can also achieve the above behaviour by looping from 1 to n. Yes that's possible but who wants to run a program which can run in O(sqrt(n)) in O(n).. We always look for the best one.
Go through the book of Cormen Introduction to Algorithms.
I will also request you to read following stackoverflow question and answers they will clear all the doubts for sure :)
Are there any O(1/n) algorithms?
Plain english explanation Big-O
Which one is better?
How do you calculte big-O complexity?
This link provides a very basic beginner understanding of O() i.e., O(sqrt n) time complexity. It is the last example in the video, but I would suggest that you watch the whole video.
https://www.youtube.com/watch?v=9TlHvipP5yA&list=PLDN4rrl48XKpZkf03iYFl-O29szjTrs_O&index=6
The simplest example of an O() i.e., O(sqrt n) time complexity algorithm in the video is:
p = 0;
for(i = 1; p <= n; i++) {
p = p + i;
}
Mr. Abdul Bari is reknowned for his simple explanations of data structures and algorithms.
Primality test
Solution in JavaScript
const isPrime = n => {
for(let i = 2; i <= Math.sqrt(n); i++) {
if(n % i === 0) return false;
}
return true;
};
Complexity
O(N^1/2) Because, for a given value of n, you only need to find if its divisible by numbers from 2 to its root.
JS Primality Test
O(sqrt(n))
A slightly more performant version, thanks to Samme Bae, for enlightening me with this. 😉
function isPrime(n) {
if (n <= 1)
return false;
if (n <= 3)
return true;
// Skip 4, 6, 8, 9, and 10
if (n % 2 === 0 || n % 3 === 0)
return false;
for (let i = 5; i * i <= n; i += 6) {
if (n % i === 0 || n % (i + 2) === 0)
return false;
}
return true;
}
isPrime(677);